3
#include<iostream.h>  
class A{  
  public:  
        int i;  
            A(int j=3):i(j){}  
};  
class B:virtual public A{  
  public:  
        B(int j=2):A(j){}  
};  
class C:virtual public A{  
  public:  
        C(int j=1):A(j){}  
};  
class D:public B, public C {    
  public:  
        D(int j=0):A(j), B(j+1), C(j+2){}  
};

int main()  
{  
    D d;   
    cout<<d.i;  
    return 0;
}

最終的な出力がどのようにゼロであるかを理解できません。jがデフォルトの方法で固定値に初期化されるたびに、クラスDのコンストラクターで初期化された値はどのようにクラスAに渡されますか?

4

2 に答える 2

2

仮想ベース継承のルールは次のとおりです。

「階層内の最も派生したクラスは、仮想ベースを構築する必要があります」

あなたの場合、最も派生したクラスからのコンストラクターを 引数を渡してD明示的に呼び出したので、 を に設定します。ルールで述べたように、仮想基本クラスはほとんどの派生クラスのみを介して構築され、中間階層を介した他のコンストラクター呼び出しは一度しか構築されないため効果がありません。A0i0

呼び出す順序は次のとおりです。

A(int)
B(int)
C(int)

よく読んだ:
なぜ仮想基底クラス コンストラクターが最初に呼び出されるのか?

于 2013-01-06T07:44:51.047 に答える
2

A は仮想基本クラスであるため、構築は 1 回だけでよいため、別のコンストラクター パラメーターを使用して作成することはできず、C++ コンパイラは基本クラスを作成する方法を 1 つ選択する必要があります。

明らかな問題は、どちらが使用されているかということです。

そしてルールは次のとおりです。 A を直接継承する最も派生したクラスで指定されたものです。

初期化の順序は単純です。最初に A (D コンストラクター初期化リストのパラメーター値を使用)、次に B (D の最初の祖先であり、以前に作成された A のインスタンスを使用)、次に C (同じ A インスタンスを共有) )、最後に D (また、B および C と同じ A オブジェクトを共有します)。

于 2013-01-06T08:06:16.667 に答える