virtualなデストラクタ
C++では、ポリモーフィズムを利用するために作成した基底クラスのデストラクタにはvirtual
を付けることがあるようです.
virtual
がないと、基底クラスのポインタで管理している場合は、基底クラスのデストラクタのみが呼ばれてしまうためです.
初心者は「そんなこと聞いてないよ」となりそうで、不親切だとは思いますが、様々な理由でこうなっているはずなので仕方ないでしょう.
以下のようなコードで確認してみましょう
#include <iostream> #include <memory> struct Base{ Base(){ std::cout << " Base constructor" << std::endl; } ~Base(){ std::cout << " Base destructor" << std::endl; } }; struct Child : public Base{ Child(){ std::cout << " Child constructor" << std::endl; } ~Child(){ std::cout << " Child destructor" << std::endl; } }; int main(){ { std::cout << "unique_ptr:" << std::endl; std::unique_ptr<Base> pBase = std::make_unique<Child>(); } { std::cout << "shared_ptr" << std::endl; std::shared_ptr<Base> pBase = std::make_shared<Child>(); } std::cout << "Raw pointer" << std::endl; Base* pBaseRaw = new Child(); delete(pBaseRaw); return 0; }
実行結果はこうなります
unique_ptr: Base constructor Child constructor Base destructor shared_ptr Base constructor Child constructor Child destructor Base destructor Raw pointer Base constructor Child constructor Base destructor
Rawポインタとunique_ptr
では、Childのデストラクタが呼ばれていないのが確認できます.
基底クラスのデストラクタにvirtual
をつければ、全てChildのデストラクタを呼ぶようになります
また、shared_ptr
はvirtualデストラクタがないにもかかわらず、Childのデストラクタが呼ばれているのも面白いですね.
これは、shared_ptr
が作成時のクラスを利用してポインタを破棄してくれるからみたいです.
しかし、unique_ptr
ではやはりvirtual
が必要となるので、あまり安心はできなさそうですね.