C 言語との互換性や、IPC 用に基底クラスを POD 化しておいて、バイナリのまま通信したい場合もある。時には後方互換として仮想化すると問題のあるコードがあるため、不可能な時もある。
そこで、C++ のデストラクタの実験。A、B、C と三つクラスが継承関係にある。A のデストラクタは仮想化されていない。
% cat destructor.cpp
#include <iostream>
struct A
{
A(){ std::cout << "A" << std::endl; }
~A(){ std::cout << "~A" << std::endl; }
};
struct B: public A
{
B(){ std::cout << "B" << std::endl; }
virtual ~B(){ std::cout << "~B" << std::endl; }
};
struct C: public B
{
C(){ std::cout << "C" << std::endl; }
virtual ~C(){ std::cout << "~C" << std::endl; }
};
int main()
{
std::cout << "==> B* b" << std::endl;
B* b = new C();
delete b;
std::cout << "==> A* a" << std::endl;
A* a = new C();
delete a;
}
結果。
% g++ destructor.cpp
% ./a.out
==> B* b
A
B
C
~C
~B
~A
==> A* a
A
B
C
~A
B へのポインタに C を割り当てた場合では、C を破棄する時にしっかりと C から A までの全てのデストラクタが呼ばれる。B が起点になり、C のデストラクタから実行する。それに引き替え、A へのポインタを通して破棄したときは、当然、B と C のデストラクタは呼ばれない。
要は使い方次第なのだが、コードの量が多くなると把握しづらい事。多相性と継承を多用しつつ、この様なコードを入れると、勘違いして正しい動作を把握できない、または理解できない者達が少なくないので、止めておいた方が無難な様だ。
セコメントをする