コンストラクタで仮想関数呼び出しても適用されない
http://www.geocities.jp/ky_webid/cpp/language/009.html
コンストラクタ内ではオーバーライドの効果が出ないようですね。
#include <iostream> class CBase { public: CBase(); virtual void foo (); void call (); }; class CSub : public CBase { public: void foo (); }; CBase::CBase () { foo(); } void CBase::foo () { std::cout << "CBase::foo" << std::endl; } void CBase::call () { foo(); } void CSub::foo () { std::cout << "CSub::foo" << std::endl; } int main () { CSub obj; obj.call(); return 0; }
$ main CBase::foo CSub::foo
call関数の呼び出しではちゃんとCSubのfoo関数が呼び出されていますが、コンストラクタの方ではCBaseのfoo関数が呼び出されてしまっています。
ちょっとややこしいですね。virtualを付けたらコンストラクタであってもちゃんと適応されてほしいところなんですが。
もし、コンストラクタ内で仮想関数を呼び出したときに、サブクラス側の関数が呼び出されてしまうと問題が起こることがあるため、このような仕組みになっています。継承関係にある2つのクラスの、コンストラクタが呼び出される順序を思い出して下さい。スーパークラス→サブクラス の順番でした。つまり、スーパークラス側のコンストラクタが呼び出された時点では、まだサブクラス側はコンストラクタが呼び出されていません。よって、まだメンバ変数の準備ができていない状態なのです。サブクラスがオーバーライドした関数が、サブクラスのメンバ変数をアクセスしていると問題になります。
一応こういう事情があるのでそれはそれでしょうがないですね。
でもデストラクタでも試してみたところ、やはりCBaseのfoo関数が呼ばれてしまいました。上記のような初期化の問題は発生しないのでデストラクタの場合はCSubのfoo関数が呼ばれても良いと思うのですが何故呼ばれないんでしょうか。謎ですね。