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. 無断での引用、転載を禁じます。