データや関数を含むクラスの内部構造は複雑なので、 オブジェクトの初期化やクラス終結処理は、単純なデータ構造の場合より格段に複雑です。コンストラクターやデストラクターは、クラス・オブジェクトの構成や 破棄に使用されるクラスの特殊なメンバー関数です。構成では、オブジェクトのストレージ割り当てや初期化もあわせて 行われる場合があります。破棄に際しては、オブジェクトのメモリーの終結処理や割り振り解除も 行われる場合があります。
他のメンバー関数と同様、コンストラクターとデストラクターは、クラス宣言の中で宣言されます。 これらは、インラインまたはクラス宣言の外で定義することができます。 コンストラクターは、デフォルトの引数を持つことができます。 コンストラクターは、他のメンバー関数と異なり、メンバー初期化リストを持つことができます。 コンストラクターとデストラクターには、次の制約事項が適用されます。
コンストラクターとデストラクターは、メンバー関数と同じアクセス規則に従います。 例えば、protected アクセスを使用してコンストラクターを宣言した場合、 それを使用してクラス・オブジェクトを使用できるのは、派生クラスとフレンドだけです。
コンパイラーは、クラス・オブジェクトを定義するときはコンストラクターを、 クラス・オブジェクトがスコープ外に出るときはデストラクターを、それぞれ自動的に呼び出します。 コンストラクターは、その this ポインターが参照するクラス・オブジェクトにメモリーを割り振ることはありませんが、そのクラス・オブジェクトが参照するオブジェクトより多くのオブジェクトにストレージを割り振る場合があります。オブジェクトのためにメモリーの割り振りが必要な場合、コンストラクターは、明示的に new 演算子を呼び出すことができます。 終結処理時に、デストラクターは、 対応するコンストラクターによって割り当てられたオブジェクトを解放します。 オブジェクトを解放するには、delete 演算子を使用します。
派生クラスはその基底クラスのコンストラクターやデストラクターを継承または多重定義しませんが、 基底クラスのコンストラクターやデストラクターを呼び出します。 デストラクターは、virtual というキーワードで宣言できます。
コンストラクターは、ローカルまたは一時クラス・オブジェクトが作成されるときにも呼び出され、 デストラクターは、ローカルまたは 一時オブジェクトがスコープを超えたときに呼び出されます。
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "void A::f()" << endl; }
virtual void g() { cout << "void A::g()" << endl; }
virtual void h() { cout << "void A::h()" << endl; }
};
struct B : A {
virtual void f() { cout << "void B::f()" << endl; }
B() {
f();
g();
h();
}
};
struct C : B {
virtual void f() { cout << "void C::f()" << endl; }
virtual void g() { cout << "void C::g()" << endl; }
virtual void h() { cout << "void C::h()" << endl; }
};
int main() {
C obj;
}
上記の例の出力は、以下のとおりです。
void B::f()
void A::g()
void A::h()
例では obj という名前で型 C のオブジェクトを作成しますが、B のコンストラクターは、C が B から派生しているので、C でオーバーライドされた関数は、いずれも呼び出しません。
コンストラクター、またはデストラクターで typeid または dynamic_cast 演算子を使用でき、同様に、コンストラクターのメンバー初期化指定子も使用できます。