なぜこのコードは:
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を使用しています)
コンパイラがC++ 11標準をサポートしている場合、using
を使用したコンストラクター継承があります(しゃれを意図しています)。詳細については、 Wikipedia C++ 11の記事 を参照してください。あなたが書く:
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
using A::A;
};
これはすべてか、または何もありません-一部のコンストラクターのみを継承することはできません。これを記述すると、すべてのコンストラクターを継承します。選択したものだけを継承するには、個々のコンストラクターを手動で記述し、必要に応じて基本コンストラクターを呼び出す必要があります。
歴史的に、コンストラクタはC++ 03標準では継承できませんでした。独自に基本実装を呼び出すことで、それらを1つずつ手動で継承する必要がありました。
コンストラクターは継承されません。これらは、子コンストラクターによって暗黙的または明示的に呼び出されます。
コンパイラーは、デフォルトのコンストラクター(引数のないもの)とデフォルトのコピーコンストラクター(同じ型への参照である引数のあるもの)を作成します。ただし、intを受け入れるコンストラクタが必要な場合は、明示的に定義する必要があります。
class A
{
public:
explicit A(int x) {}
};
class B: public A
{
public:
explicit B(int x) : A(x) { }
};
UPDATE:C++ 11では、コンストラクターを継承できます。詳細については、須磨の回答を参照してください。
Bでコンストラクタを明示的に定義し、親のコンストラクタを明示的に呼び出す必要があります。
B(int x) : A(x) { }
または
B() : A(5) { }
テンプレート関数を使用してすべてのコンストラクターをバインドするのはどうですか?
template <class... T> Derived(T... t) : Base(t...) {}
これは 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
}
正しいコードは
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番目にベースクラスパラメーターコンストラクターのコンストラクターを呼び出すためのベースクラスイニシャライザーが必要です。