ゲームが作れるようになるまでがんばる日記

ゲーム制作のことを中心にゲームに関することを書いています

コンストラクタやデストラクタ内で仮想関数を呼ばない

Effective C++ 第2章9項
基底クラスのコンストラクタやデストラクタ内で仮想関数を呼ぶようにしても、派生クラスで実装した仮想関数は呼ばれない。派生クラスのオブジェクトを作成した時はまず基底クラスのコンストラクタが実行されるが、その時にはまだ派生クラスの部分は作成されていない。またデストラクタの場合は先に派生クラスの部分が破棄されるので、基底クラスのデストラクタ内では派生クラスの部分を呼ぶことはできない。

#include <iostream>
using namespace std;

class Base
{
public:
    Base() {
        func();
    }
    virtual void func() = 0;
};

class Test : public Base
{
public:
    Test() {}
    virtual void func() {
        cout << "Test::func" << endl;
    }
};

int main()
{
    Test obj;
}

このソースの場合、純粋仮想関数として定義されているfunc()を派生クラスTestで実装して、基底クラスBaseのコンストラクタで呼び出そうとしているが、このプログラムをビルドしようとしてもBaseのfunc()が実装されていないとリンクエラーとなる。
以前、このことを知らない時に実際にコードを書いていて、どうして派生クラスの関数が実行されないのだろうとハマったことがあった。その時には仮想関数にするのをやめて、コンストラクタで基底クラスにパラメータとして必要な情報を引数で渡すようにして対処した。