禁用屏幕拷贝(Print Screen),调用派生的析构函数及其它......
2007-03-15 21:56:11 来源:WEB开发网核心提示: Figure 3 反汇编后的 vdtor.exeFigure 3 展示了 vdtor.cpp 的反汇编代码,CBase 和 CDerived 都有 Finalize 方法;Figure 4 是派生类 CDerived 的 Finalize 方法,禁用屏幕拷贝(Print Screen),调
Figure 3 反汇编后的 vdtor.exe
Figure 3 展示了 vdtor.cpp 的反汇编代码。CBase 和 CDerived 都有 Finalize 方法;Figure 4 是派生类 CDerived 的 Finalize 方法。它还说明了编译器为每个类创建了一个特殊的 __dtor 方法。该方法在你调用 delete 时被调用。如果你检查一下主入口函数 main 的微软中间语言(IL)代码,你会看到如下的代码行:
// delete pBase;
IL_0008: ldloc.0
IL_0009: call instance void CBase::__dtor()
当你 delete 某个托管对象时,编译器产生一个对 __dtor 方法的调用。但编译器调用的是哪个 __dtor 方法呢?因为我将 pBase 声明为一个 CBase 指针(CBase*),编译器便调用 CBase::__dtor,正如前面的代码段所示。这似乎就是说 CDerived 在析构期间被旁路掉了,直到你看到 CBase::__dtor 实现:
// in CBase::__dtor()
IL_0000: ldarg.0
IL_0001: call void [mscorlib]System.GC::SuppressFinalize(object)
IL_0006: ldarg.0
IL_0007: callvirt instance void CBase::Finalize()
IL_000c: ret
__dtor 函数用 callvirt 调用 Finalize,即使你从没听说过IL,也能猜到那是一个调用虚拟方法的指令。无论实际对象是哪个,公共语言运行时(CLR)都调用 Finalize 方法——此处是 CDerived。为了强制期望的 C++ 析构语义,每个 Finalize 方法显式地调用其基类的 Finalize 方法,正像你在 CDerived::Finalize 所看到的那样:
// in CDerived::Finalize()
IL_000b: ldarg.0
IL_000c: call instance void CBase::Finalize()
这里编译器产生一个常规调用指令,而非 callvirt。否则你的程序将出现死循环直到耗尽堆栈。
更多精彩
赞助商链接