【问题标题】:How to Avoid Duplicate copies of Base Class Members in Derived Class in C++如何避免 C++ 派生类中基类成员的重复副本
【发布时间】:2012-04-07 14:43:24
【问题描述】:

在我的项目中,有一个基类和三个不同的派生类。我在基类中有一些宏变量写为 const int 。所有派生成员都将访问这些成员并且将看到相同的值。因为它是一个常量,并且不会改变,所以保持 3 个不同的值会浪费空间。因此,我想要一种方法来只维护一个基类 const 成员的副本,以便所有派生类都使用相同的。

例子

 //Base.hpp
 Class Base {

       const int ZER0;
       const int ONE;
 };

 //Derived1.hpp
 class Derived1:public Base {
      int some_method1(); 
 };

  //Derived1.cpp

  int Derived1::some_method1() {

    int value = ZERO;
  }

 //Derived2.hpp

 class Derived2:public Base {
    int some_method2();
 };

//Derived2.cpp

int Derived2::some_method2() {
   int value = ONE;
}

//main.cpp

Derived1 d1;
d1->some_method1();

Derived d2;
d2->some_method2();

//在这两种方法中,值都是恒定的,但零和一仍然会有不同的空间。有没有办法,我只维护一个副本?我可以想到静态变量。在类中使用静态是否可以,我在哪里初始化静态变量。请指教。

PS:这个问题可能是重复的,但是我找不到类似的东西,如果你觉得是这样,请随时重定向到相应的文章/问题;

【问题讨论】:

  • 我在这里闻到了“我的第一个本土 RTTI 实现”的味道,如果是这样,请使用 dynamic_cast 处理此类事情。
  • 也许你应该考虑使用static类成员。
  • ^是的,我想静态是要走的路,我要使用它。

标签: c++ inheritance static macros constants


【解决方案1】:

如果我对您的理解正确,枚举会满足您的需求吗?

class Base
{
    enum 
    {
        ZERO,
        ONE
    };
};

【讨论】:

  • 这取决于,零和一只是我程序中的示例,不一定是零和一后跟两个。当然我们可以使用 enum 来定义变量,但我的问题是,如果 enum 有零和一,那么派生类 d1 和 d2 会看到多少个副本?如果有两个,不,如果两个元素的副本只有一个,是的,这就是我要找的:)
  • @howtechstuffworks 枚举常量不是变量,而是在编译时硬连接到程序中的文字值;没有任何“副本”-它甚至不会影响您的类或任何对象的大小,因为它在内存中不存在(您不能获取枚举常量的地址,因为它没有地址)。当然,您仍然可以声明 int 变量来存储这些值,但 enum 声明本身没有运行时占用空间。
  • 哇,那我猜这会有所帮助,谢谢!。还有一个问题,所以我可以在我的类中声明枚举并在派生类中访问它,对吗?否则枚举不关心类?
  • 是的,枚举将遵循与您可能在其中声明的任何其他内容(包括成员函数、成员变量、typedef、内部类等)完全相同的访问/可见性规则.由于派生类只是基类的扩展,因此指定 Base::ZERO 将与 Derived::ZERO 具有完全相同的含义(假设您没有用其他东西“隐藏”派生类中的基定义)
  • 啊,我现在明白了。稍微偏离主题,您需要的函数将是 ::write() 而不是 ::read()。但无论如何,您可以使用 static const int 的地址。
【解决方案2】:

我认为您可以使用虚拟基础继承来维护一份 base ..

//Base.hpp
class Base {
public:
    Base() {}
    virtual ~Base() {}
protected:
    static const int ZER0;
    static const int ONE;
};

//Base.cpp
const int Base::ZER0 = 0;
const int Base::ONE = 1;

//Derived1.hpp
class Derived1 : public virtual Base {  //using virtual keyword here maintains one copy of base class, thus one copy of ONE and ZERO for all objects since they are static members of Base. You must read about diamond problem of virtual inheritence to understand this properly.

public:
    Derived1() :Base() {}
    int method1();
};

//Derived1.cpp

int Derived1::method1() {
    int value = ZER0;
    return value;
}

//Derived2.hpp

class Derived2 : public virtual Base {
public:
    Derived2() :Base() {}
    int method2();
};

//Derived2.cpp

int Derived2::method2() {
    int value = ONE;
    return value;
}

//main.cpp


int main() {
    Derived1 d1;
    d1.method1();  // . instead of -> , -> is used for member access through pointers

    Derived2 d2;
    d2.method2();

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 2011-07-17
    • 2021-11-30
    相关资源
    最近更新 更多