具有虚拟多重继承的构造函数定义

ant*_*npp 3 c++ inheritance multiple-inheritance

我认为一个例子最能描述我的问题。

struct Base {
    Base() = delete;
    Base(int x) : x(x) {}
    int x;
};

struct Derived1 :  virtual Base {
    Derived1(int y) : Base(5), y(y) {}
    int y;
};

struct Derived2 :  virtual Base {
    Derived2(int z) : Base(10), z(z) {}
    int z;
};

struct Derived3: Derived1, Derived2 {
public:
    Derived3(int y, int z) : Derived1(y), Derived2(z) {}

};
Run Code Online (Sandbox Code Playgroud)

我得到一个错误: In constructor ‘Derived3::Derived3(int, int)’: error: use of deleted function ‘Base::Base()’ Derived3(int y, int z) : Derived1(y), Derived2(z) {}

我不明白为什么会出现这个错误。在我看来,所有的基类实际上得到通过它们的构造函数初始化在这个例子中(明确Derived1Derived2和含蓄Base通过Derived2(我不知道这里,也许通过Derived1))。好吧,让我们做编译器告诉我的事情。

struct Derived3: Derived1, Derived2 {
public:
    Derived3(int y, int z) : Base(-1), Derived1(y), Derived2(z) {}

};
Run Code Online (Sandbox Code Playgroud)

它编译,如果我现在这样做:

Derived3 d = Derived3(7, 9);
std::cout << d.x << std::endl;
std::cout << d.y << std::endl;
std::cout << d.z << std::endl;
Run Code Online (Sandbox Code Playgroud)

我明白了-1, 7, 9。这根本不是我想要的。一个想法是用它的一个派生类初始化基类,我期望第一个数字是 5 或 10。

所以,这是我的问题:Base当它已经在派生类之一中完成时,为什么我被迫显式调用构造函数?

更具体地说,因为我有多重继承和虚拟继承,我相信任何实例Derived3都只有一个Base类实例的副本。而且我期望Base在它的派生类(Derived1Derived2)中初始化此副本,但正如我清楚地看到的那样,它不能以这种方式工作=(我哪里错了?

Rya*_*anP 6

当您使用虚拟继承时,只有 1 个 Base 副本。谁应该初始化该副本,派生 1 还是派生 2?没有办法知道。这就是为什么您在 Derived 3 中被迫自己做这件事,所以不会有歧义。这也是为什么你得到你得到的输出而不是 5 或 10。

如果没有虚拟继承,派生 1 和派生 2 都将拥有自己负责的 Base 副本,因此没有歧义。当你强迫他们从同一个基础继承时,Derived 3 必须获得 Base 的所有权才能解决歧义......虚拟继承充其量是奇怪的。