デストラクターでの仮想関数呼び出し

C++ デストラクターで仮想関数を呼び出しています。

一般的に、どのような仮想関数もコンストラクターやデストラクターから呼び出すべきではありません。コンストラクターやデストラクターから仮想関数を呼び出しても、現在コンストラクターまたはデストラクターを実行しているクラス以外の派生クラスには移動しません。つまり、生成時およおび破棄時には、仮想関数は仮想ではありません。

例えば、デストラクターで仮想関数 f を呼び出すクラス A があると仮定します。A の派生クラス B に固有のメンバー関数 f がある場合、 B のインスタンス破棄時に、A のデストラクターは B のデストラクターよりも後に呼び出されます。A のデストラクターが f を呼び出すと、B にある f の定義ではなく、A にある f の定義が呼び出されます。これは、この時点では派生クラスがすでに破棄されているためです。B にある f の定義は、B のデストラクターが呼び出さた後に呼び出すことはできません。

ID

問題箇所

説明

1

呼び出し位置

仮想関数が呼び出された場所


#include <stdio.h>

class A
{
public:
    A() {
    }

    void intermediate_call() {
        virtual_function();
    }

    virtual void virtual_function() {
        printf("A::virtual_function called\n");
    }

    virtual ~A() {
        // Bad: virtual function call during object destruction
        intermediate_call();
    }
};

class B : public A
{
public:
    // override virtual function in A
    void virtual_function() {
        printf("B::virtual_function called\n");
    }
};

int main(int argc, char **argv)
{
    B myObject;

    // This call behaves like a normal virtual function call.
    // Print statement shows it invokes B::virtual_function.
    myObject.virtual_function();

    // Call to virtual_function during destruction doesn't
    // behave like normal virtual function call.
    // Print statement shows it invokes A::virtual_function,
    // even though we are destroying an instance of B, not A.
}
        

© 2010 Intel Corporation. 無断での引用、転載を禁じます。