web-dev-qa-db-ja.com

コンストラクターの継承

なぜこのコードは:

class A
{
    public: 
        explicit A(int x) {}
};

class B: public A
{
};

int main(void)
{
    B *b = new B(5);
    delete b;
}

これらのエラーの結果:

 main.cpp:関数 'int main()':
 main.cpp:13:エラー: 'B :: B(int)'の呼び出しに一致する関数がありません
 main.cpp:8:注:候補:B :: B()
 main.cpp:8:注:B :: B(const B&)

BはAのコンストラクタを継承すべきではありませんか?

(これはgccを使用しています)

190
Sydius

コンパイラがC++ 11標準をサポートしている場合、usingを使用したコンストラクター継承があります(しゃれを意図しています)。詳細については、 Wikipedia C++ 11の記事 を参照してください。あなたが書く:

class A
{
    public: 
        explicit A(int x) {}
};

class B: public A
{
     using A::A;
};

これはすべてか、または何もありません-一部のコンストラクターのみを継承することはできません。これを記述すると、すべてのコンストラクターを継承します。選択したものだけを継承するには、個々のコンストラクターを手動で記述し、必要に応じて基本コンストラクターを呼び出す必要があります。

歴史的に、コンストラクタはC++ 03標準では継承できませんでした。独自に基本実装を呼び出すことで、それらを1つずつ手動で継承する必要がありました。

334
Suma

コンストラクターは継承されません。これらは、子コンストラクターによって暗黙的または明示的に呼び出されます。

コンパイラーは、デフォルトのコンストラクター(引数のないもの)とデフォルトのコピーコンストラクター(同じ型への参照である引数のあるもの)を作成します。ただし、intを受け入れるコンストラクタが必要な場合は、明示的に定義する必要があります。

class A
{
public: 
    explicit A(int x) {}
};

class B: public A
{
public:
    explicit B(int x) : A(x) { }
};

UPDATE:C++ 11では、コンストラクターを継承できます。詳細については、須磨の回答を参照してください。

84
Avi

Bでコンストラクタを明示的に定義し、親のコンストラクタを明示的に呼び出す必要があります。

B(int x) : A(x) { }

または

B() : A(5) { }
7
grepsedawk

テンプレート関数を使用してすべてのコンストラクターをバインドするのはどうですか?

template <class... T> Derived(T... t) : Base(t...) {}
4
Pradu

これは Bjarne Stroustrupのページ から直接です:

そのように選択した場合でも、初期化が必要な新しいメンバー変数を定義する派生クラスのコンストラクターを継承することにより、自分自身を撃つことができます。

struct B1 {
    B1(int) { }
};

struct D1 : B1 {
    using B1::B1; // implicitly declares D1(int)
    int x;
};

void test()
{
    D1 d(6);    // Oops: d.x is not initialized
    D1 e;       // error: D1 has no default constructor
}
4
nenchev

正しいコードは

class A
{
    public: 
      explicit A(int x) {}
};

class B: public A
{
      public:

     B(int a):A(a){
          }
};

main()
{
    B *b = new B(5);
     delete b;
}

エラーはb/cです。クラスBにはパラメーターコンストラクターがなく、2番目にベースクラスパラメーターコンストラクターのコンストラクターを呼び出すためのベースクラスイニシャライザーが必要です。

2
Iqbal Haider