新規記事の投稿を行うことで、非表示にすることが可能です。
2017年12月20日
《その190》 仮想デストラクタ
仮想デストラクタ
下記のプログラムで、Bbb は、クラス Aaa から public派生したクラスです。
【下記プログラムをそのまま実行した場合】
main関数では、
Aaa* ptr = new Bbb;
として Bbb型オブジェクトを動的に生成し、
delete ptr;
で、それを破棄しています。
実行結果を先に示します。
この実行結果から、デストラクタ ~Bbb が呼ばれないままプログラムが終了していることがわかります。
ポインタ ptr の静的な型が Aaa*型なので、Aaa型のデストラクタが呼び出されてしまうのです。
その結果、動的に確保した配列 p 用の領域が解放されないままになってしまいます。
【下記プログラムで、デストラクタ ~Aaa を仮想デストラクタに変更した場合】
今度は、クラス Aaa のデストラクタを仮想デストラクタにしてみます。
具体的には、下記のプログラムの ★部分のコメントアウトを外して、
virtual ~Aaa();
とするだけです。
こうすることで、派生クラスのデストラクタ ~Bbb も、仮想デストラクタになります。
したがって、クラス Bbb は、仮想関数を含む多相的クラスということになります。
すると、
delete ptr;
によって呼び出されるのは、動的な型、つまりこの場合は、
ptr が指すオブジェクト型のデストラクタ ~Bbb です。
この場合の実行結果は次のようになります。
こんどは、終了時に、デストラクタ ~Bbb が呼ばれるので、配列の領域も解放されています。
以下は、プログラムです。
// ------------------------------------
#include <iostream>
using namespace std;
class Aaa {
public:
Aaa() {
cout << "constructor Aaa\n";
}
// virtual // ★
~Aaa() {
cout << "destructor ~Aaa\n";
}
};
class Bbb : public Aaa {
int* p;
public:
Bbb() {
p = new int[10];
cout << "constructor Bbb\n";
}
~Bbb() {
delete[] p;
cout << "destructor ~Bbb\n";
}
};
int main() {
Aaa* ptr = new Bbb;
delete ptr;
}
// ------------------------------------