5

在下面的代码中,我试图创建一个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 

我知道objBase1是虚拟继承,但在构建obj时,Level2Level1也需要构建,这导致在其每个结构中都有Base1。但整个构建过程只调用一次Base1构造函数。我无法解释这一点。这是否意味着Base1Level2Level1里面objBase1共享相同的数据,直接属于obj

+3

虚拟继承的重点在于您只有*一个虚拟基础子对象。 –

+0

你知道,与C中不同的是,在C++中,空参数列表是简单的(),对吧? – curiousguy

回答

4

但整个构建过程只调用一次Base1构造函数。我无法解释这一点。

解释是Base1是层次结构中所有类的虚拟基础。这正是虚拟基础以及它们的用途:共享公共基类实例。从cppreference

行情对于被指定的虚拟每个不同的基类,最派生对象包含该类型的仅一种碱基类子对象,即使类出现在继承层次多次(如只要它每次都是虚拟继承的)。

所有虚拟基子对象的任何非虚基类子对象之前初始化,所以只有最派生类中调用它的成员初始化列表中的虚拟基础的构造函数:

以虚拟继承进去,你的结构图可以被认为是这样的:

obj 
--Level2 
----Base2 
----+-------Base1 
--Level1 // 
----Base2// 
----+----//
--+-------/ 

这是否意味着内部的obj股价在2级以及1级的有基础1基础1相同的数据直接属于OBJ?

是的。在obj的整个结构中只有一个Base1实例。

1

这是否意味着Base2在Level2和Level1内部obj与Base1直接属于obj共享相同的数据?

是的,还有的Base1只有一个子对象,并通过Level2Level1基子在Leaf类共享。

下面是与例如从标准的说明,$ 10.1/6多个基类[class.mi](强调矿)

对于另一示例,

class V { /* ... */ }; 
class A : virtual public V { /* ... */ }; 
class B : virtual public V { /* ... */ }; 
class C : public A, public B { /* ... */ }; 

为的目的c类型C,类型为V的单个子对象是 由每个基本子对象c共享,该子对象具有虚拟基类 类型V。鉴于以上定义的类别C,类C的对象将 具有V的一个子对象,如下所示。