2017-10-23 10 views
4

ベースクラスコンストラクタと継承を呼び出すという概念を実装しようとしています。次のコードを記述しましたが、クラスAのデフォルトコンストラクタを宣言しないと、なぜ私はエラーが発生しているのだろうか。ベースクラスコンストラクタを呼び出すときにデフォルトコンストラクタを宣言する

#include <iostream> 
using namespace std; 

class A 
{ 
    int a; 
    public: 
    A() {} //Default Constructor 
    A(int x) 
    { 
     a=x;cout<<a; 
     cout<<"A Constructor\n"; 
    } 
}; 
class B: virtual public A 
{ 
    int b; 
    public: 
    B(int x) 
    { 
     b=x;cout<<b; 
     cout<<"B Constructor\n"; 
    } 
}; 
class C: virtual public A 
{ 
    int c; 
    public: 
    C(int x) 
    { 
     c=x;cout<<c; 
     cout<<"C Constructor\n"; 
    } 
}; 
class D: public B,public C 
{ 
    int d; 
    public: 
    D(int p,int q,int r,int s):A(p),B(q),C(r) 
    { 
     d=s;cout<<d; 
     cout<<"D Constructor\n"; 
    } 
}; 
int main() 
{ 
    D d(1,2,3,4); 
    return 0; 
} 
+2

具体的にはどのエラーですか? – user0042

+1

'A'デフォルトコンストラクタは' B'と 'C'クラスに暗黙的に使用されます。何年も前にこの質問が出てきたことを覚えているので、私は正式ではわかりません。答えがあったのは、このような場合、 'B'と' C'の暗黙的な初期化は存在しないとみなされるべきです。とにかく、これらの初期化は事実上無視されます。これは、仮想基底クラスが、最も派生したクラス( 'D')の中で初期化されるためです。はい、C++での仮想継承の概念は少し汚れています。 –

答えて

2

あなたはサブクラスでスーパークラスのコンストラクタを呼び出すいけない場合は、Bのインスタンスを作成したい場合は、スーパークラスの自動作成されたインスタンスが存在しますので、スーパークラスは、デフォルトコンストラクタを持っている必要がありますデフォルトのコンストラクタがない場合は不可能です。

1

現時点では、クラスとDの存在を忘れてしまいましょう。

それはB::B(int)を使用します

B b(10); 

として、あなたはタイプ Bのオブジェクトを構築した場合。 B::B(int)の実装では、 BA部分は何とか初期化する必要があります。あなたは持っている: Aはデフォルトコンストラクタを持っていないので、コンパイラは正しくそのエラーとして報告

B(int x) : A() 
{ 
    b=x;cout<<b; 
    cout<<"B Constructor\n"; 
} 

:と同等です

B(int x) 
{ 
    b=x;cout<<b; 
    cout<<"B Constructor\n"; 
} 

を。

あなたは使用していることを修正することができます:BのコンストラクタからA(int)に別の値を渡すことができるようにしたいと思い

B(int x) : A(0) 
{ 
    b=x;cout<<b; 
    cout<<"B Constructor\n"; 
} 

をする場合は、ユーザが2つの引数を使用してBを構築できるようにする必要があります。

B(int x, int y = 0) : A(y) 
{ 
    b=x;cout<<b; 
    cout<<"B Constructor\n"; 
} 
+0

しかし、クラス 'B'は、OPのコードで最も派生したクラスとして使われていません。個別のコンパイルのサポートは、事実上、そのケースに特別なルールがないことが必要であると主張することができます。しかし、私はそれほど確信していません。 –

+0

@ Cheersandhth.-Alfでは、 'B'がインスタンス化されるか' D'がインスタンス化されるかにかかわらず、 'B(int)'は正しく処理される必要があります。 –

+0

@ R.Sahu:最も派生したクラスがBの場合は*、ベースクラスの場合はBが異なることに注意してください。後者の場合、必ずしも 'A'コンストラクタを呼び出す必要はありません。これは、最も派生したクラスから呼び出されています。異なる動作をさせる1つの方法は、 'A()'を呼び出すかどうかの動的チェックを実行するBコンストラクタのコードを生成することです。別の方法は、Bのインスタンス化の場所で 'A()'を呼び出すことです。後者の場合、リンカーエラーを回避することができます。したがって、標準が許す/保証するものに関する質問は開いている。 –

関連する問題