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

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() {
        intermediate_call();
    }

    void intermediate_call() {
        // Bad: virtual function call during object construction
        virtual_function();
    }

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

    virtual ~A() {
    }
};

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)
{
    // Call to virtual_function during construction doesn't
    // behave like normal virtual function call.
    // Print statement shows it invokes A::virtual_function,
    // even though we are constructing an instance of B, not A.
    B myObject;

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

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