2012-02-07 12 views
31

Aが基本クラスであり、BAから派生するクラス階層を考えてみましょう。なぜ暗黙のコピーコンストラクタが基本クラスのコピーコンストラクタを呼び出し、定義されたコピーコンストラクタが呼び出されないのですか?

コピーコンストラクタがBで定義されていない場合、コンパイラは1つを合成します。呼び出されると、このコピーコンストラクタはを基本クラスのコピーコンストラクタ(ユーザーが何も提供していない場合でも合成されたもの)を呼び出します。

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

出力:


ユーザーがBに独自のコピーコンストラクタを定義する場合

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Copy constructor 
、呼び出されたとき、このコピーコンストラクタは、への呼び出しがない限り、基本クラスのデフォルトコンストラクタ 呼び出します。基本クラスのコピーコンストラクタが明示的に存在します(初期化リストなど)。

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
    B(const B& rhs) { 
     std::cout << "B::Copy constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

出力:

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Default constructor 
B::Copy constructor 

私の質問は、なぜユーザー定義のコピーコンストラクタは、デフォルトの動作として、基本クラスのコピーコンストラクタを呼び出すことはありませんか?

+2

これがデフォルトの場合は、そのようなことが起こりたくない場合をどのように指定しますか? – PlasmaHH

+0

@PlasmaHH 'ParentClass()'を初期化子リストに追加します。それはまだかなり矛盾し、私は信じている混乱するだろう。 –

+0

@マークB:確かに、私は彼がそれについて考えて同じ結論に来ることを望んでいた... – PlasmaHH

答えて

7

これは暗黙のコピーコンストラクタが定義されている方法です(デフォルトを呼び出すのは意味がありません)。任意のコンストラクタ(コピーなど)を定義するとすぐに、通常の自動動作ではデフォルトの親コンストラクタを呼び出すので、特定のユーザ定義コンストラクタに対してそのコンストラクタを変更するのは矛盾します。

1

単純な(おそらくは真面目な)答えは、あなたがそれを伝えなかったからです。派生コピーコンストラクタを記述しているので、その動作方法を完全に制御できます。ベースとコンパイラの呼び出しを指定できなかった場合、ベースクラスのデフォルトのコンストラクタを呼び出すことによって、ベースクラスを初期化するコードが生成されます。

8

すべての基本子コンストラクタは親のデフォルトコンストラクタを呼び出します。標準がどのように定義されているかです。あなたが指摘したように、あなたがAのコピーコンストラクタを呼び出すために基本クラスBを望んでいた場合は、明示的にコンパイラは親のconstuctorべきそれぞれ異なるコンストラクタに知ることができないので、これがそうであるそれのため

#include <iostream> 

class A { 
int a; 
public: 
A() { 
    std::cout << "A::Default constructor" << std::endl; 
} 

A(const A& rhs) { 
    std::cout << "A::Copy constructor" << std::endl; 
} 
}; 

class B : public A { 
int b; 
public: 
B() { 
    std::cout << "B::Default constructor" << std::endl; 
} 
B(const B& rhs):A(rhs) { 
    std::cout << "B::Copy constructor" << std::endl; 
} 
}; 

int main(int argc, const char *argv[]) 
{ 
std::cout << "Creating B" << std::endl; 
B b1; 
std::cout << "Creating B by copy" << std::endl; 
B b2(b1); 
return 0; 
} 

を聞いています呼び出されるので、デフォルトのコンストラクタがあります。他のすべての場合、明示的に状態を設定する必要があります。

+5

'すべての基本子コンストラクタが親のデフォルトコンストラクタを呼び出します。... ...暗黙のコピーコンストラクタを除いて:)! –

+0

暗黙のコピーコンストラクタは、コンパイラによって提供される最も基本的な操作の明示的な名前です。 IMOはちょうど素晴らしい名前です。 – shakthi

関連する問題