引用を例で説明しましょう。あなたがこれらのクラスを持っているとしましょう、
struct A { A(int x) {} };
struct B : virtual A { B(int x) : A(x) {} };
struct C : virtual A { C(int x) : A(x) {} };
注:A
仮想ベースです!
ここで、とD
からの派生を定義します。B
C
struct D : B, C
{
//correct constructor - because A(x) is "present" in the initialization-list
D(int x) : A(x), B(x), C(x) { }
//wrong constructor - because A(x) is "absent" from the initialization-list!
//D(int x) :B(x), C(x) { }
};
は階層内で最もD
派生したクラスであることに注意してください。したがって、初期化の責任はであり、そのため、コンストラクターの初期化リストに明示的に書き込みます(上記を参照)。とだけを書くと、コンパイルすらできなくなります。これを参照してください:http ://www.ideone.com/sO6m5 A
D
D
A(x)
B(x)
C(x)
しかし、一度書くA(x)
と、うまくコンパイルされます。これを参照してください:http ://www.ideone.com/kiwh0
ここでもう一度引用を読み、太字のテキストに注意してください。
仮想ベースクラスの初期化を管理するルールは、非仮想ベースのルールよりも複雑で直感的ではありません。仮想ベースを初期化する責任は、階層内で最も派生したクラスが担っています。新しい派生クラスが階層に追加されるとき、仮想ベース(直接および間接の両方)の初期化の責任を引き受ける必要があります
この説明がコンセプトの理解に役立つことを願っています!