在下面的代码中,我尝试创建一个Leaf
对象obj
来查看多层继承中的构造函数顺序,但我发现obj
的结构和构造函数调用这个案子有点奇怪。
#include<iostream>
using namespace std;
class Base1 {
public:
Base1(void) {
cout << "class Base1" << endl;
}
};
class Base2 {
public:
Base2(void) {
cout << "class Base2" << endl; }
};
class Level1 : public Base2, virtual public Base1
{
public:
Level1(void)
{
cout << "class Level1" << endl;
}
};
class Level2 : public Base2, virtual public Base1
{
public:
Level2(void)
{
cout << "class Level2" << endl;
}
};
class Leaf :virtual public Level2, virtual public Level1
{
public:
Leaf(void)
{
cout << "class Leaf" << endl;
}
};
int main(void)
{
Leaf obj;
return 0;
}
输出显示构造函数调用:
class Base1
class Base2
clase Level2
class Base2
class Level1
class Leaf
但是程序结尾的obj结构实际上是:
obj
--Level2
----Base2
----Base1
--Level1
----Base2
----Base1
--Base1
我知道Base1
的{{1}}是虚拟继承的,但在构建obj
期间,还需要构建obj
和Level2
,在每个结构中都会导致Level1
。但整个构建过程只调用Base1
构造函数一次。我无法解释这一点。这是否意味着Base1
中的Base1
和Level2
内的Level1
与直接属于obj
的{{1}}共享相同的数据?
答案 0 :(得分:4)
但整个构建过程只调用一次Base1构造函数。我无法解释这一点。
解释是Base1
是层次结构中所有类的虚拟基础。这正是虚拟基础及其用途:共享公共基类实例。
对于指定为virtual的每个不同的基类,最派生的对象只包含该类型的一个基类子对象,即使该类在继承层次结构中多次出现(只要它每次都是虚拟继承)。
所有虚拟基础子对象在任何非虚拟基础子对象之前初始化,因此只有最派生的类在其成员初始化列表中调用虚拟基础的构造函数:
考虑虚拟继承,您的结构图可以被认为是这样的:
obj
--Level2
----Base2
----+-------Base1
--Level1 / /
----Base2 / /
----+----/ /
--+-------/
这是否意味着Level2中的Base1和obj中的Level1与直接属于obj的Base1共享相同的数据?
是。 Base1
的整个结构中只有一个obj
个实例。
答案 1 :(得分:1)
这是否意味着Level2中的Base1和obj中的Level1与直接属于obj的Base1共享相同的数据?
是的,Base1
只有一个子对象,并且由Level2
的{{1}}和Level1
的基础子对象共享。
以下是标准的示例解释,$ 10.1 / 6多个基类[class.mi](强调我的)
另一个例子,
Leaf
对于类类型
class V { /* ... */ }; class A : virtual public V { /* ... */ }; class B : virtual public V { /* ... */ }; class C : public A, public B { /* ... */ };
的对象c
,类型C
的单个子对象是 由具有虚拟基类的V
的每个基础子对象共享 输入c
。鉴于上面定义的类V
,类C
的对象将会 有一个<{1}}的子对象,如下所示。