pyt*_*hor 9 c++ destruction vptr
我正在看这篇文章,它说"在进入基类析构函数后,该对象成为基类对象,而C++的所有部分 - 虚函数,dynamic_casts等 - 以这种方式对待它." 这是否意味着vptr在破坏期间发生了变化?这是怎么发生的?
Dav*_*eas 11
在使用虚函数表(即所有当前C++实现)的所有实现中,答案是肯定的,vptr即对正在执行的析构函数类型的更改.其原因是,该标准要求被破坏的对象的类型是被exectued析构函数的类型.
如果有三种类型的B,d,MD(碱,衍生,大多数衍生)的层次结构和实例化和破坏类型的对象MD,则在执行MD::~MD()该对象的类型是 MD,但是当到基座析构所述隐式呼叫执行时,对象的运行时类型必须是 D.这是通过更新vptr.
当然,迂腐的C++答案是"标准没有说明vtbls或多态如何实现."
但实际上,是的.在基类的析构函数体开始执行之前修改vtbl.
编辑:
以下是我使用MSVC10来看待自己的情况.一,测试代码:
#include <string>
#include <iostream>
using namespace std;
class Poly
{
public:
virtual ~Poly();
virtual void Foo() const = 0;
virtual void Test() const = 0 { cout << "PolyTest\n"; }
};
class Left : public Poly
{
public:
~Left()
{
cout << "~Left\n";
}
virtual void Foo() const { cout << "Left\n"; }
virtual void Test() const { cout << "LeftTest\n"; }
};
class Right : public Poly
{
public:
~Right() { cout << "~Right\n"; }
virtual void Foo() const { cout << "Right\n"; }
virtual void Test() const { cout << "RightTest\n"; }
};
void DoTest(const Poly& poly)
{
poly.Test();
}
Poly::~Poly()
{ // <=== BKPT HERE
DoTest(*this);
cout << "~Poly\n";
}
void DoIt()
{
Poly* poly = new Left;
cout << "Constructed...\n";
poly->Test();
delete poly;
cout << "Destroyed...\n";
}
int main()
{
DoIt();
}
Run Code Online (Sandbox Code Playgroud)
现在,在Polydtor的左大括号处设置一个断点.
当你运行这段代码时,它会在开始大括号上打破(就在构造函数的主体开始执行之前),你可以看一看vptr:
此外,您可以查看Polydtor 的反汇编:
Poly::~Poly()
{
000000013FE33CF0 mov qword ptr [rsp+8],rcx
000000013FE33CF5 push rdi
000000013FE33CF6 sub rsp,20h
000000013FE33CFA mov rdi,rsp
000000013FE33CFD mov ecx,8
000000013FE33D02 mov eax,0CCCCCCCCh
000000013FE33D07 rep stos dword ptr [rdi]
000000013FE33D09 mov rcx,qword ptr [rsp+30h]
000000013FE33D0E mov rax,qword ptr [this]
000000013FE33D13 lea rcx,[Poly::`vftable' (13FE378B0h)]
000000013FE33D1A mov qword ptr [rax],rcx
DoTest(*this);
000000013FE33D1D mov rcx,qword ptr [this]
000000013FE33D22 call DoTest (13FE31073h)
cout << "~Poly\n";
000000013FE33D27 lea rdx,[std::_Iosb<int>::end+4 (13FE37888h)]
000000013FE33D2E mov rcx,qword ptr [__imp_std::cout (13FE3C590h)]
000000013FE33D35 call std::operator<<<std::char_traits<char> > (13FE3104Bh)
}
000000013FE33D3A add rsp,20h
000000013FE33D3E pop rdi
000000013FE33D3F ret
Run Code Online (Sandbox Code Playgroud)
跳过下一行,进入析构函数体,然后再看一下vptr:
现在,当我们DoTest从析构函数体内调用时,vtbl已经被修改为指向purecall_,这会在调试器中生成运行时断言错误:
| 归档时间: |
|
| 查看次数: |
1750 次 |
| 最近记录: |