Visual Studio 2008、c++、win32、ドットネットなしを使用しています。
親のデストラクタで呼び出される仮想関数に問題があります。たとえば、クラス a と b を取り上げます。クラス a には、Hello() という仮想関数があります。呼び出されると、hello が出力されます。
クラス b はクラス a を継承し、関数 Hello も実装します。呼び出されると、world が出力されます。
クラス a のデストラクタでは、関数 Hello が呼び出されます。クラス b が削除されると、まず b のデストラクタが呼び出され、次に a のデストラクタが呼び出されます。a のデストラクタでは、関数 Hello が呼び出されますが、それはクラス b ではなくクラス a に関連付けられた実装です。
この例のコードは、この行の下にあります。
class a{
public:
virtual void Hello();
a();
~a();
};
a::a(){
};
a::~a(){
Hello();
}
void a::Hello(){
printf("hello\n");
}
class b:public a{
public:
virtual void Hello();
b();
~b();
};
b::b(){
}
b::~b(){
}
void b::Hello(){
printf("world\n");
}
int _tmain(int argc, _TCHAR* argv[]){
a* exampleA=new a();
b* exampleB=new b();
exampleA->Hello();
exampleB->Hello();
delete exampleA;
delete exampleB;
return 0;
}
出力は次のとおりです。
hello
world
hello
hello
クラス b のデストラクタにブレークポイントを配置すると、ローカル変数の __vfptr は次のようになります。
__vfptr
[0x0] 0x002314ce b::Hello(void)
ステップスルーしてクラス a のデストラクタに入ると、ローカル変数の __vfptr が次のように変更されます。
__vfptr
[0x0] 0x0024c864 a::Hello(void)
これは普通ですか?そして、クラス a のデストラクタ内で Hello の b の実装を呼び出す (正しい) 方法はありませんか?