4

次のおもちゃクラス A とその子 B があります。

#include <iostream>

using namespace std;

class A
{
    protected:
        int a;
    public:
        A():a(1){cout<<"A default constructor..."<<endl;}
        A(int i):a(i){cout<<"A non-default constructor..."<<endl;}
        A(const A &ao){cout<<"A copy constructor..."<<endl; a=ao.a;}
};

class B:public A
{
    private:
       int b;
    public:
       B(int i,int j):A(i),b(j){cout<<"B constructor..."<<endl;}
       //B(const B &bo){cout<<"B copy constructor... "<<endl; b=bo.b;}
       void print(){cout<<endl<<"class B, a: "<<a<<" b: "<<b<<endl<<endl;}
};

int main()
{
    B b1(3,8);
    b1.print();
    B b2=b1;
    b2.print();
}

クラス B にコピー コンストラクターを提供しないと、コンパイラーが合成してくれ、クラス A に提供したコピー コンストラクターを使用することがわかりました。ただし、クラス B にコピー コンストラクターを提供すると、基本クラス A のコピー コンストラクターを明示的に呼び出さない場合 (コードを参照)、コンパイラーはクラス A の既定のコンストラクターを呼び出しますか? 何故ですか?

4

4 に答える 4

9

これは標準的な動作です。これは主に一貫性のためです。特定の基底クラス コンストラクターを明示的に呼び出さないユーザー定義のコンストラクターは、既定のコンストラクターを呼び出しますコピー コンストラクタが異なるのはなぜですか?

于 2013-09-08T19:20:54.363 に答える
1

派生クラスのコンストラクター (任意のコンストラクター) を作成する場合、そのコンストラクターの初期化子リストで基本クラスのサブオブジェクトを明示的に初期化できます(多くの場合、初期化する必要があります)。そうしないと、コンパイラーはそれらの基本クラスのサブオブジェクトが使用可能であると仮定して、それらのデフォルトのコンストラクターを暗黙的に呼び出します。この規則は、すべてのユーザー定義コンストラクターに適用されます。

これはまさにあなたの場合に起こったことです。Aのコンストラクターで baseを初期化するのを忘れたB::B(const B&)ため、その base には既定のコンストラクターが使用されました。B::B(const B&)この場合、それがコピー コンストラクターであるという事実は何の違いもありません。繰り返しになりますが、すべての種類のユーザー定義コンストラクターに対して一貫して機能します。

現在、ユーザー定義のコピー コンストラクターを指定しない場合、コンパイラは暗黙的に on を提供しようとします。暗黙的に定義されたコピー コンストラクターは、すべての基本クラスのコピー コンストラクターを呼び出そうとします。言語仕様は、コンパイラが提供するコピー コンストラクターがそのように動作することを示しているだけです。これは、「なぜ」という質問に対する答えです。

于 2013-09-08T20:09:10.663 に答える
0

ここでは、初期化規則の順序が適用されます。独自のコンストラクターを提供することによってのみ、そのルールを置き換えることができます。

于 2013-09-08T20:08:54.893 に答える