コンストラクタとデストラクタ
C++ には、クラスのオブジェクトの作成、初期化、コピー、および破棄の方法を決定する特殊なメンバ関数がいくつかあります。コンストラクタとデストラクタは、そのなかで最も重要なメンバ関数です。それらは、通常のメンバ関数の特徴(たとえば、クラス内で宣言と定義を行うか、クラス内で宣言してクラス外で定義するなど)の多くを持っていますが、以下のような独特の特徴を持っています。
- 戻り値の宣言を持ちません(void さえ持ちません)。
- 継承させることはできません。ただし、派生クラスで、基底クラスのコンストラクタやデストラクタを呼び出すことはできます。
- コンストラクタは、ほとんどの C++ 関数と同様に、デフォルトの引数を取ったり、メンバの初期化リストを使用することができます。
- デストラクタは virtual にすることができますが、コンストラクタはできません (仮想デストラクタを参照)。
- 次のようなコードによって、これらの関数のアドレスを取得することはできません。
int main (void) { . . . void *ptr = base::base; // illegal . . . }
- コンストラクタとデストラクタは、明示的に定義されていない場合、コンパイラによって生成されます。また、それらは、プログラムで明示的に呼び出さなくても、頻繁に呼び出されます。コンパイラによって生成されたコンストラクタやデストラクタは、すべてパブリックになります。
- コンストラクタは、通常の関数を呼び出すようにして呼び出すことはできません。デストラクタは、完全修飾名を使用すれば呼び出すことができます。
{ . . . X *p; . . . p->X::~X(); // legal call of destructor X::X(); // illegal call of constructor . . . }
- オブジェクトを定義したり破棄するときは、コンパイラが自動的にコンストラクタやデストラクタを呼び出します。
- オブジェクトの割り当てが必要な場合は、コンストラクタやデストラクタが暗黙的に new 演算子や delete 演算子を呼び出します。
- コンストラクタやデストラクタを持つオブジェクトは、共用体のメンバとして使用することはできません。
- あるクラス X に、特定の型を受け付けるコンストラクタが定義されていない場合は、他のコンストラクタを検索したり、割り当てられた値を、クラス X のコンストラクタが受け付ける型に変換する変換関数を検索する試みは行われません。このルールは、1 つのパラメータを持ち、"=" 構文を使用した初期化リストを持たないコンストラクタにのみ適用されます。
class X { /* ... */ X(int); }; class Y { /* ... */ Y(X); }; Y a = 1; // illegal: Y(X(1)) not tried
クラス X が複数のコンストラクタを持つ場合は、クラス X のオブジェクト x が定義されるたびに、これらのコンストラクタのうちの 1 つが呼び出されます。そのコンストラクタが x を作成して初期化します。デストラクタは、コンストラクタによって作成されたクラス オブジェクトを破棄することによって、その逆の処理を実行します。
クラスのローカル(一時)オブジェクトを作成するときも、コンストラクタが呼び出されます。これらのオブジェクトがスコープから出るときに、デストラクタが呼び出されます。