2012-03-11 16 views
1

私はエラーが発生します:Bのための適切なデフォルトのコンストラクタがありません。しかし、私は引数を与えるときにコンパイラがデフォルトのコンストラクタを呼び出す理由を理解していません。デフォルト。継承:適切なデフォルトのコンストラクタがありません

#include <iostream> 
using namespace std; 

class A { 
    int i; 
public: 
    A(int ii) { i = ii; cout << "Constructor for A\n"; } 
    ~A() { cout << "Destructor for A\n"; } 
    void f() const{} 
}; 

class B { 
    int i; 
public: 
    B(int ii) { i = ii; cout << "Constructor for B\n"; } 
    ~B() { cout << "Destructor for B\n"; } 
    void f() const{} 
}; 

class C:public B { 
    A a; 
public: 
    C() { cout << "Constructor for C\n"; } 
    ~C() { cout << "Destructor for C\n"; } 
    void f() const { 
     a.f(); 
     B::f(); 
    } 
}; 

class D:public B { 
    C c; 
public: 
    D(int ii) { B(ii); cout << "Constructor for D\n"; } 
    ~D() { cout << "Destructor for D\n"; } 
}; 

int main() { 
    D d(47); 
} 

答えて

4

あなたの親のコンストラクタは、初期化子リストで呼び出されなければなりません。

class D:public B { 
    C c; 
public: 
    D(int ii) : B(ii)/* <- */ { cout << "Constructor for D\n"; } 
    ~D() { cout << "Destructor for D\n"; } 
}; 

注意/ * < - * /コメント。それは変更する必要があります。

は何あなたが今やっていることは使用されていないあなたのクラスDのコンストラクタでB()のインスタンスを作成することです:

D(int ii) { B(ii); /* <- useless*/ } 
+0

ありがとう – talha099

+0

CもBを継承しています。 –

+0

これは同じ解決策ですね。 – mfontanini

2
D(int ii) { B(ii); cout << "Constructor for D\n"; } 

Bのデフォルトコンストラクタを呼び出します。 B(ii)は、Bの一時オブジェクトを作成します。この一時オブジェクトは、コンストラクタがDになるとすぐに破棄されます。つまり、構築中のオブジェクトのBaseクラスのコンストラクタは呼び出されません。

ソリューション:
あなたはMember Initializer listを使用する必要がありますあなたの基本クラスの特定のコンストラクタを呼び出すことができるようにします。

D(int ii) : B(ii) 
{ 
} 
+0

CもBから継承します。 –

+1

@LuchianGrigore:同じ問題があるのは不思議ではありません。 OPはメンバーのイニシャライザリストに気づいていないと思います。答えがそれを指摘してくれると思います.OPのコメントはS /彼がここでの回答を通して理解していることを示しています。 –

+0

十分に公正で、それを指摘するだけです。 –

1

このコード:

class C:public B 
{ 
    C() { cout << "Constructor for C\n"; } 
}; 

試みへBのデフォルトのコンストラクタを呼び出します。あなたが望むかもしれない

class C:public B 
{ 
    C() : B(0) { cout << "Constructor for C\n"; } 
}; 

それがあなたのロジックに依存します。

も間違っている:

D(int ii) { B(ii); cout << "Constructor for D\n"; } 

それは単に行っていない一時オブジェクトを作成し、子クラスのコンストラクタの本体内の基底クラスのコンストラクタを呼び出す

D(int ii) : B(ii) { cout << "Constructor for D\n"; } 

する必要があります何でも期待する動作を得るには、のイニシャライザリストのコンストラクタを呼び出す必要があります。

1

Bから派生したDを作成していますが、DのctorはBのコンストラクタにパラメータを渡さないため、Bにはデフォルトのctorが必要です。

は、この問題を解決するには、通常Bのctorのにパラメータを提供するために、Dを記述する必要があります。

class D : public B { 
    C C; 
public: 
    D(int ii) : B(ii) { cout << "ctor for D\n"; } 
}; 
あなたはそのベースとメンバーサブオブジェクトを実現する必要が
1

あなたは、コンストラクタの体内に入る時間によって構築されています!

D(int ii): B(ii) { std::cout << "constructor for D\n"; } 

あなたがDコンストラクタのあなたの体の中に構築されたオブジェクトだけである:あなたがメンバー初期化子リストでその引数を渡す必要がデフォルトを持っていないベースまたはメンバーを持っている場合、つまり、あなたのケースで本当に目的を果たしていない一時的なオブジェクト(一時的なオブジェクトは、場合によっては役に立つかもしれません)。

関連する問題