Tips #018 デストラクタ中の仮想関数
仮想関数は奥が深い。
仮想関数はどこでも仮想だと思ったら大間違いだ。
以下のプログラムを見て欲しい。
class A { virtual ~A() { foo2(); } virtual void foo() { printf( "class A :: foo()\n" ); } void foo2() { foo(); } }; class B : public A { void foo() { printf( "class B :: foo()\n" ); } }; void main() { A * p = new B; p->foo2(); delete p; }
class A の foo2() は仮想関数 foo() を呼び出しているのだが、
main() 中の p->foo2() では派生クラスである class B の foo() が呼び出される。
しかし class A のデストラクタ ~A() 中の foo2() では class A の foo() が呼び出される。
基底クラス class A のデストラクタ実行時は、すでに派生クラス class B が破棄されたあとなので仮想関数テーブルが利かないのである。
ああややこしや。
以上です。