您的位置:首页 > 编程语言 > C语言/C++

学习C++反汇编-多继承

2016-03-06 15:26 549 查看
C++源代码:

#include<iostream>

class CSofa
{
public:
CSofa()
{
Color = 2;
}
virtual ~CSofa()
{
printf("virtual ~CSofa()\r\n");
}
virtual int GetColor()
{
return Color;
}
virtual void SitDown()
{
printf("sit and relax\r\n");
}
protected:
int Color;
};

class CBed
{
public:
CBed()
{
Length = 4;
Width = 5;
}
virtual ~CBed()
{
printf("virtual ~CBed()\r\n");
}
virtual int GetArea()
{
return Length*Width;
}
virtual void Sleep()
{
printf("go to sleep\r\n");
}
protected:
int Length;
int Width;
};

class CSofaBed :public CSofa, public CBed
{
public:
CSofaBed()
{
Height = 4;
}
virtual ~CSofaBed()
{
printf("virtual ~CSofaBed()\r\n");
}
virtual void SitDown()
{
printf("sit and relax on the sofa bed\r\n");
}
virtual void Sleep()
{
printf("go to sleep on the sofa bed\r\n");
}
virtual int GetHeight()
{
return Height;
}
protected:
int Height;
};

int main()
{
CSofaBed SofaBed;
}
生成的汇编代码:

class CSofaBed :public CSofa, public CBed
{
public:
CSofaBed()
003018B0  push        ebp
003018B1  mov         ebp,esp
003018B3  push        0FFFFFFFFh
003018B5  push        3064C8h
003018BA  mov         eax,dword ptr fs:[00000000h]
003018C0  push        eax
003018C1  sub         esp,0CCh
003018C7  push        ebx
003018C8  push        esi
003018C9  push        edi
003018CA  push        ecx
003018CB  lea         edi,[ebp-0D8h]
003018D1  mov         ecx,33h
003018D6  mov         eax,0CCCCCCCCh
003018DB  rep stos    dword ptr es:[edi]
003018DD  pop         ecx
003018DE  mov         eax,dword ptr ds:[0030B004h]
003018E3  xor         eax,ebp
003018E5  push        eax
003018E6  lea         eax,[ebp-0Ch]
003018E9  mov         dword ptr fs:[00000000h],eax
003018EF  mov         dword ptr [this],ecx
{
003018F2  mov         ecx,dword ptr [this] 以对象首地址作为this指针
003018F5  call        CSofa::CSofa (030103Ch) 调用沙发类构造函数
{
003018FA  mov         dword ptr [ebp-4],0
00301901  mov         ecx,dword ptr [this]
00301904  add         ecx,8 将this指针调整到第二个虚表指针地址处
00301907  call        CBed::CBed (03011DBh) 调用床类构造函数
0030190C  mov         eax,dword ptr [this]
0030190F  mov         dword ptr [eax],308BB0h 设置虚表指针
00301915  mov         eax,dword ptr [this]
00301918  mov         dword ptr [eax+8],308BC8h 设置虚表指针
Height = 4;
0030191F  mov         eax,dword ptr [this]
00301922  mov         dword ptr [eax+14h],4
}

virtual ~CSofaBed()
{
001C1A40  push        ebp
001C1A41  mov         ebp,esp
001C1A43  sub         esp,0CCh
001C1A49  push        ebx
001C1A4A  push        esi
001C1A4B  push        edi
001C1A4C  push        ecx
001C1A4D  lea         edi,[ebp-0CCh]
001C1A53  mov         ecx,33h
001C1A58  mov         eax,0CCCCCCCCh
001C1A5D  rep stos    dword ptr es:[edi]
001C1A5F  pop         ecx
001C1A60  mov         dword ptr [this],ecx
001C1A63  mov         eax,dword ptr [this]
001C1A66  mov         dword ptr [eax],1C8BB0h
001C1A6C  mov         eax,dword ptr [this]
001C1A6F  mov         dword ptr [eax+8],1C8BC8h 将两个虚表指针设置为各个父类的虚表首地址
printf("virtual ~CSofaBed()\r\n");
001C1A76  push        1C8BD8h
001C1A7B  call        _printf (01C13A2h)
001C1A80  add         esp,4
}
001C1A83  mov         ecx,dword ptr [this]
001C1A86  add         ecx,8
001C1A89  call        CBed::~CBed (01C1069h)
001C1A8E  mov         ecx,dword ptr [this]
}
001C1A91  call        CSofa::~CSofa (01C1091h)
001C1A96  pop         edi
001C1A97  pop         esi
001C1A98  pop         ebx
001C1A99  add         esp,0CCh
001C1A9F  cmp         ebp,esp
001C1AA1  call        __RTC_CheckEsp (01C116Dh)
001C1AA6  mov         esp,ebp
001C1AA8  pop         ebp
001C1AA9  ret
在子类的构造过程中,根据继承关系的顺序,首先调用了父类CSofa的构造函数。在调用另一个父类CBed时,并不是直接将对象的首地址作为this指针传递,而是向后调整了父类CSofa的长度,以调整后的地址值作为this指针,最后再调用父类CBed的构造函数。由于有了两个父类,因此子类在继承时也将它们的虚表指针一起继承了过来,也就有了两个虚表指针。在对父类进行析构时,由于具有多个父类,调用各个父类的析构函数时传递的首地址将有所不同,编译器会根据每个父类在对象中占用的空间位置,对应地传入各个父类部分的首地址作为this指针。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: