C++ 在派生 class 中替换基 class

C++ replace base class in derived class

我相信我正在考虑这个 "badly"(非 C++'y)。这是我正在尝试做的事情

class AA {
    public:
        AA(const char* name, unsigned short number);

        int Write(int x);
    ...
    }

class BB: public AA {
    public:
        BB(const char* name, unsigned short number, const char* other);
        BB(AA aaObj, const char* other);

        int Write(double y, int x) {
            /* do something */
            AA::Write(x)
            }
    ...
    }

在第二个 BB 构造函数中,我想用 aaObj 替换 BB 的基础对象。我不想要副本,我希望实际的基础对象相同(相同的引用)。

问题:

  1. 这可能吗?
  2. 这是个坏主意吗?
  3. 是否有更好的模式(工厂生产具有共享成员的对象?

这是不可能的。想想 class 层次结构,例如 nesting dolls。派生的 class 是外面的那个,每个连续的基础 class 是一个嵌套的娃娃。由于基础 classes 包含在派生 class 中,因此您不能使用另一个基础 class 作为派生对象的基础 class。

如果您希望多个对象共享同一个对象,您可以做的一件事是使用 std::shared_ptr 成员。这样每个对象都可以有一个指向同一个对象的指针。

每个派生实例都有自己的任何基础实例class,你无法绕过这个。要使派生类型引用相同的基实例,需要将其从派生 is-a 关系更改为成员 has-a(然后该成员需要是引用或指针)。

我在那个职位上会做的事情是这样的:

class BB{
public:
    BB(AA& aaObj, const char* other)
    {
        basepointer = &aaobj;
    }

    int Write(double y, int x) {
        basepointer->Write(x);
    }


private:
    AA* basepointer;
};

这两个 class 在内存布局上 通常 彼此不匹配(例如,您可能在 BB 中有其他数据成员)。此外,由于您在构造函数中,您已经在创建一个新对象。

除非您确定 AA 最初是 BB class(或 [=13= 的子 class,否则您不能向下转换为 BB ]).例如:

BB b;
AA * a = dynamic_cast<AA *> (&b);
/* use initialization code for AA on a */
/* Now you could do (though this example becomes a bit weird): */
BB *bb = dynamic_cast<BB *> (a);

为什么要避免复制?你有大量的数据成员吗?在这种情况下,请考虑使用 shared_ptr on the relevant class members and implement an assignment-operator。所以这样做:

AA a;
/* ... */
BB b;
b = a;

BB b(a)

成为分配 shared_ptr 的唯一问题,因此非常便宜。

简单回答您的问题:

  1. 不是当前形式,可能是通过 down 铸造。但是这个 可能是一个糟糕的设计。

  2. 是的。应该是吧。

  3. 如果您有很多成员,例如字符串等,请考虑:保留对 AA 的引用,将 AA 复制到 BB (这可能不是很大的成本),重构这样你就可以 直接实例化 BB 而是将 upward 发送到 AA 到您的初始化例程。

为了提供更详细的建议,我们需要更多关于您尝试优化的特定问题的代码或信息。

从问题的描述来看,您似乎想要组合而不是继承。 特别是 这样你的 Write 函数就不是虚函数了(重载非虚函数只在 CRTP 设计中有意义,而你的 class 不是 CRTP) .

然后,如果你切换到合成,你可以使用一个指向拥有对象的(智能)指针,并随意替换它。