下面是我所询问的示例代码。输出将是XXbBACY,但我不明白为什么。
#include <iostream>
using namespace std;
class X {
public:
X() { cout << 'X'; }
X(char c) { cout << 'X' << c; }
};
class A : virtual X {
public:
A() : X('a') { cout << 'A'; }
};
class B : X {
public:
B() : X('b') { cout << 'B'; }
};
class C : virtual X {
public:
C() : X('c') { cout << 'C'; }
};
class Y : A, virtual B, C {
public:
Y() { cout << 'Y'; }
~Y() {}
};
int main() {
Y y;
return 0;
}
根据我的理解,当我们创建类y的对象y时,因为不是所有的基类都是从类X(特别是B(派生的,所以y中会有3个类X的实例。
构造对象y时调用的第一个构造函数将是类B的构造函数,因为它实际上是从类y派生的,但在构造类B之前,必须创建类X的实例,因为B() : X('b') { cout << 'B'; }
是类B的默认构造函数,X(char c) { cout << 'X' << c; }
将在类X中调用。它将打印Xb。现在我们返回到类B,默认构造函数将打印B,然后返回到类Y
现在,类A和类C的一个实例将以类似的方式构建,留下一个输出:XbBXaAXcCY
我的理解似乎完全错误,因为输出是XXbBACY,这怎么可能呢?
施工顺序总是这样:
- 首先是所有(直接或间接(虚拟基,顺序为深度优先声明顺序。显然,任何一种类型中最多只能有一种
- 接下来,按声明顺序排列非虚拟基
- 按申报顺序排列的所有其他成员
- 最后,ctor主体。现在,您可以安全地直接或间接调用虚拟函数,它们将根据当前运行的ctor进行解析
在您的情况下,这意味着:
- CCD_ 3与CCD_
virtual B
来自Y::B
:
(第一步:X
来自Y::B::X
。(- CCD_ 9从CCD_。
X
虚拟基地已经完成 - CCD_ 12从CCD_。
X
虚拟基地已经完成
销毁顺序颠倒了这一点。