22

問題:

class Base {
public:
  Base(Base* pParent);
  /* implements basic stuff */
};

class A : virtual public Base {
public:
  A(A* pParent) : Base(pParent) {}
  /* ... */
};

class B : virtual public Base {
public:
  B(B* pParent) : Base(pParent) {}
  /* ... */
};

class C : public A, public B {
public:
  C(C* pParent) : A(pParent), B(pParent) {} // - Compilation error here
  /* ... */
};

指定された位置で、gcc は Base() への関数呼び出し、つまりデフォルトのコンストラクターと一致しないと文句を言います。しかし、C は Base から直接継承せず、A と B を介してのみ継承します。では、なぜ gcc はここで文句を言うのでしょうか?

アイデア?ティア/ロブ

4

3 に答える 3

46

virtual基本クラスは、仮想基本から継承する中間基本クラスではなく、最も派生したクラスによって初期化されるという点で特別です。潜在的な複数のイニシャライザのうち、1 つのベースを初期化するための正しい選択はどれですか?

構築中の最派生クラスがメンバー初期化リストにリストされていない場合、仮想基本クラスは、存在し、アクセス可能でなければならないデフォルト コンストラクターで初期化されます。

仮想ベース識別子は、問題のクラスの直接のベースでなくても、コンストラクターの初期化子リストで使用できることに注意してください。

于 2010-01-24T09:15:54.923 に答える
8

C から Base のコンストラクターを明示的に呼び出す必要があります。

class C : public A, public B {
public:
C(C* pParent) : Base(pParent), A(pParent), B(pParent) {}
/*... */
};
于 2010-01-24T09:17:03.040 に答える
5

カスタム コンストラクターを宣言すると、既定のコンストラクターは無効になります。仮想継承では、仮想継承されたコンストラクターを直接呼び出す必要があります。そうしないと、A で初期化するか B で初期化するかがわからないためです。

于 2010-01-24T09:06:24.207 に答える