仮想関数は、コンストラクタの中で(C++プログラマーにとっては)奇妙な振る舞いをする。
たとえば、以下のコードを実行すると、出力されるのは「Set by initializer」である。
class Program
{
public static void Main(string[] args)
{
new Derived("Constructed in main");
}
}
class B
{
protected B()
{
// 1. ベースクラスのコンストラクタが呼び出される
VFunc(); // 2. VFunc() は派生クラスのものが呼び出される
}
protected virtual void VFunc()
{
WriteLine("VFunc in B");
}
}
class Derived : B
{
private readonly string _msg = "Set by initializer";
public Derived(string msg)
{
_msg = msg;
}
protected override void VFunc()
{
// 3. ベースクラスのコンストラクタによって呼び出される
// このとき、派生クラスのコンストラクタはまだ呼ばれてないので、
// _msgは初期化子で設定された値になっている
WriteLine(_msg);
}
}
一般に、コンストラクタで仮想関数を実行すると、コードがひどく壊れやすくなる。
派生クラスが何をするか完全にコントロールすることはできないからだ。
コンストラクタ内での仮想関数の実行は禁止すべき(Never call)である。