我刚刚写了一些代码,我试图了解对象是如何被多态破坏的。
#include <iostream>
struct Base {
virtual ~Base() {
std::cout << "base destructed\n";
}
};
struct Derived : public Base{
virtual ~Derived() {
std::cout << "derived destructed\n";
}
};
int main() {
Derived der;
Base bases1[2], bases2[2], bases3[2], bases4[2];
//case 1
new(bases1) Derived(der);
std::cout << "((Base*)bases1)->~Base();\n";
((Base*)bases1)->~Base();
//case 2
new(bases2) Derived(der);
std::cout << "\nbases2->~Base();\n";
bases2->~Base();
//case 3
new(bases3) Derived(der);
std::cout << "\nbases3[0].~Base();\n";
bases3[0].~Base();
//case 4
new(bases4) Derived(der);
std::cout << "\n(*bases4).~Base();\n";
(*bases4).~Base();
getchar();
return 0;
}
我对上述代码的了解:
- 在情况 1 中,bases1 指向派生对象的开头(包括一个 vptr),它是一个基指针,所以就像我们在基指针上删除的通常情况一样(我的意思是破坏)。
- 在情况 2 中,bases2 是一个数组名称,但在某些情况下我们可以将其视为指向第一个对象的指针,那么情况 2 应该给我与情况 1 相同的结果吗?
- 案例 3 和案例 4 相同,它们都取消引用第一个对象,其类型为:Base,然后在其上调用析构函数。
- 这些代码是非标准的,而且很危险,但我只想弄清楚它是如何在指定的编译器上工作的(visual studio 2012)。
输出:
((Base*)bases1)->~Base();
derived destructed
base destructed
bases2->~Base();
bases3[0].~Base();
base destructed
(*bases4).~Base();
base destructed
我想知道的:
- 情况2,没有任何东西被破坏,可能的原因是什么?编译器优化?
- 在情况 3 和情况 4 中,只有碱基被破坏,这是怎么回事?对象切片?
编辑:
以下是我从反汇编窗口得到的:
((Base*)bases1)->~Base();
00D96CF9 mov esi,esp
00D96CFB push 0
00D96CFD mov eax,dword ptr [bases1]
00D96D00 lea ecx,[bases1]
00D96D03 mov edx,dword ptr [eax]
00D96D05 call edx
00D96D07 cmp esi,esp
00D96D09 call __RTC_CheckEsp (0D91992h)
bases2->~Base(); //empty
bases3[0].~Base();
00D96DB0 push 0
00D96DB2 mov eax,4
00D96DB7 imul eax,eax,0
00D96DBA lea ecx,bases3[eax]
00D96DBE call Base::`vector deleting destructor' (0D91A0Ah) //array delete?
(*bases4).~Base();
00D96E14 push 0
00D96E16 mov eax,4
00D96E1B imul eax,eax,0
00D96E1E lea ecx,bases4[eax]
00D96E22 call Base::`vector deleting destructor' (0D91A0Ah) //aray delete?
我看不懂汇编程序,有人可以给我一个合理的解释吗?