5

次のコードでは、オブジェクトobjを作成して、多層継承でコンストラクタの順序を確認しようとしましたが、構造体がobjであり、コンストラクタが少し奇妙な場合があります。私はobjBase1がある知っている仮想継承での直接ベースの構築方法は?

obj 
--Level2 
----Base2 
----Base1 
--Level1 
----Base2 
----Base1 
--Base1 

class Base1 
class Base2 
clase Level2 
class Base2 
class Level1 
class Leaf 

をしかし、プログラムの最後に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; 
} 

コール仮想継承されるが、objの構築時には、Level2およびLevel1も構築する必要があり、それぞれの構造においてBase1に至る。しかし、全体の建設プロセスはBase1コンストラクターを1回呼び出すだけです。私はこれを説明することはできません。これは、に直接属しているBase1と同じデータを共有するLevel2Level1の中のBase1を意味しますか?

+3

仮想継承の全ポイントは、* 1つの*仮想ベースのサブオブジェクトしか持たないことです。 –

+0

C言語とは異なり、C++では空のパラメータリストは単純に '()'です – curiousguy

答えて

4

しかし、全体の構築プロセスでは、Base1コンストラクタが1回しか呼び出されません。私はこれを説明することはできません。

Base1は、階層内のすべてのクラスの仮想ベースです。これはまさに仮想基盤であり、共通基底クラスインスタンスを共有するためのものです。仮想指定された各個別の基底クラスのcppreference

から

引用、最も派生オブジェクトは、AS(クラスが継承階層に何回現れても、そのタイプの唯一つのベースクラスサブオブジェクトが含まれています毎回バーチャルに継承されている限り)。

すべての仮想ベースサブオブジェクトが任意の非仮想ベースサブオブジェクトの前に初期化されるので、唯一の最も派生クラスは、そのメンバー初期化子リストで仮想拠点のコンストラクタを呼び出します。

口座に仮想継承を取ると、あなたの構造図は、このようなものと考えることができます

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

これは、OBJ株式内部レベル2およびレベル1でBASE1直接objに属しBASE1と同じデータを意味するのでしょうか?

はい。正確には、objの構造全体に1つのBase1インスタンスがあります。

1

これは、Level2のBase1とobjのLevel1が、objに直接属しているBase1と同じデータを共有しているのでしょうか?

はい、一つだけBase1のサブオブジェクト、およびクラスLeafLevel2Level1のベースサブオブジェクトによって共有さがあります。ここ

は、標準からの例と説明の$ 10.1/6複数のベースクラス[class.mi】物体cのための(強調鉱山)別の例として

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

クラスタイプCの場合、サブタイプVのサブオブジェクトは、 のサブベースであり、すべてのサブオブジェクトで共有されます。cの仮想基本クラスはです。タイプV。上に定義されたクラスCが与えられた場合、クラスCのオブジェクトは、以下に示すようにVのサブオブジェクトのを有する。のオブジェクトは となる。