3

私は次のシナリオを持っています:

class A
{
  public:
    A(std::string id);
};

class B : public virtual A
{
  public:
    B();
};

class C : public virtual A
{
  public:
    C();
};

class D : public B, public C
{
  public:
    D(std::string id);
};


D::D(std::string id) : A(id), B(), C()
{
}


class X : public D
{
  public:
    X(std::string id);
}

X::X(std::string id) : D(id)
{
}

ここで、Dのインスタンスを作成すると、すべてが正常に機能します。ただし、Xのインスタンスを作成すると、コンパイラエラーが発生し、Aのデフォルトコンストラクタを呼び出そうとしていることを通知します。これは存在しません。作成するとコンパイルされますが、デフォルトのコンストラクターのみが呼び出されるため、idが正しく設定/初期化されません。

これは、次のようにXのコンストラクターを実装することで修正できます。

X::X(std::string id) : A(id), D(id)
{
}

しかし、私の理解では、これは不要なはずです。だから私のエラーはどこにありますか?

4

1 に答える 1

2

文字列コンストラクターはデフォルトコンストラクターをとしてマークするため、すべてのコンストラクターを作成publicし、デフォルトコンストラクターを定義する必要があります。さらに、最も派生したクラスは、ドラフト標準から引用して、仮想基本クラスを初期化しますA=delete

12.6.2ベースとメンバーの初期化[class.base.init]

10非委任コンストラクターでは、初期化は次の順序で進行します。—最初に、最も派生したクラス(1.8)のコンストラクターの場合のみ、仮想基本クラスは深さ優先探索の順序で初期化されます。 -基本クラスの有向非巡回グラフの右走査。「左から右」は、派生クラスの基本指定子リストでの基本クラスの出現順序です。

この場合、それXは実際に初期化する必要があることを意味しAます。

#include <iostream>
#include <string>

class A
{
public:
  A() { std::cout << "A\n"; }
  A(std::string id) { std::cout << id << " A(id)\n"; }
};

class B : public virtual A
{
public:
   B() { std::cout << "B\n"; }
};

class C : public virtual A
{
public:
   C() { std::cout << "C\n"; }
};

class D : public B, public C
{
public:  
   D(std::string id): A(id) { std::cout << id << " D(id)\n"; }
};


class X : public D
{
public:
  X(std::string id): A(id), D(id) { std::cout << id << " X(id)\n"; }
};

int main()
{
   X x("bla");
   x;       
}
于 2013-01-29T13:18:03.910 に答える