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

Constructor definition with virtual 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) {}

};

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

我不明白为什么会出现这个错误。在我看来,在这个例子中,所有基础 classes 实际上都是通过它们的构造函数初始化的(显式 Derived1Derived2 以及隐式 BaseDerived2 (我是在这里不确定,也许通过 Derived1))。 好吧,让我们按照编译器告诉我的去做。

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

};

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

Derived3 d = Derived3(7, 9);
std::cout << d.x << std::endl;
std::cout << d.y << std::endl;
std::cout << d.z << std::endl;

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

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

更具体地说,由于我有多重继承和虚拟继承,我相信 Derived3 的任何实例都恰好有一个 Base class 实例的副本。我期待 Base 的这个副本在它的最派生 class(Derived1Derived2)中初始化,但正如我清楚地看到它不起作用这样=(我哪里错了?

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

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