Mesoscopic Programming

タコさんプログラミング専門

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 が破棄されたあとなので仮想関数テーブルが利かないのである。
ああややこしや。

以上です。