1. 单继承,父类中没有虚函数
  2. 单继承,父类存在虚函数,子类重写虚函数
  3. 单继承,父类存在虚函数,子类不新定义虚函数
  4. 单继承,父类存在虚函数,子类新定义虚函数
  5. 单继承,父类不存在虚函数,子类定义虚函数
  6. 多继承,父类都有虚函数,子类有重写虚函数
  7. 多继承,父类1,父类2,其中父类1没有虚函数,父类2有虚函数,子类新定义虚函数
  8. 多继承,父类中都没有虚函数,子类新定义虚函数
  9. 菱形继承

  • 单继承,父类中没有虚函数
// 用于初始化列表使用的类
class CInit
{
public:
CInit(int nNumber){
m_nNumber = nNumber;
}
int m_nNumber;

    ~CInit() {
      printf("CInit析构函数调用\n");
    }

};

class CBase
{
public:
CBase()
{
printf("CBase\r\n");
}
~CBase()
{
printf("~CBase\r\n");
}
void SetNumber(int nNumber)
{
m_nBase = nNumber;
}
int GetNumber()
{
return m_nBase;
}
public:
int m_nBase;
}; class CDervie : public CBase
{
public:
void ShowNumber(int nNumber)
{
SetNumber(nNumber);
m_nDervie = nNumber + 1;
printf("%d\r\n", GetNumber());
printf("%d\r\n", m_nDervie);
}
void SetNumber(int nNumber){ // 覆盖父类成员方法
m_nBase = nNumber;
}
CDervie():m_Init(1)
{
printf("构造列表使用\r\n");
}
   ~CDervie() {

      printf("CDervie析构函数调用\r\n");
    }

public:
int m_nDervie;
int m_nBase; // 覆盖父类数据成员
CInit m_Init; // 初始化列表使用类
};

类CDervie单继承类CBase,在类CDervie中存在一个CInit类成员,

void main(int argc, char* argv[])
{ CDervie Dervie;
Dervie.SetNumber(argc);
printf("%d\r\n", Dervie.m_nBase);
printf("%d\r\n", Dervie.CBase::m_nBase);
}

内存布局

汇编

 298:      CDervie Dervie;
0114760D 8D 4D E0 lea ecx,[Dervie]
01147610 E8 A5 B7 FF FF call CDervie::CDervie (01142DBAh)
01147615 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
299: Dervie.SetNumber(argc);
0114761C 8B 45 08 mov eax,dword ptr [argc]
0114761F 50 push eax
01147620 8D 4D E0 lea ecx,[Dervie]
01147623 E8 66 B6 FF FF call CDervie::SetNumber (01142C8Eh)
300: printf("%d\r\n", Dervie.m_nBase);
01147628 8B 45 E8 mov eax,dword ptr [ebp-18h] //
0114762B 50 push eax
0114762C 68 68 2E 1E 01 push offset string "%d\r\n" (011E2E68h)
01147631 E8 94 9D FF FF call _printf (011413CAh)
01147636 83 C4 08 add esp,8
301: printf("%d\r\n", Dervie.CBase::m_nBase);
01147639 8B 45 E0 mov eax,dword ptr [Dervie] //
301: printf("%d\r\n", Dervie.CBase::m_nBase);
0114763C 50 push eax
0114763D 68 68 2E 1E 01 push offset string "%d\r\n" (011E2E68h)
01147642 E8 83 9D FF FF call _printf (011413CAh)
01147647 83 C4 08 add esp,8

构造函数

CDervie::CDervie (01142DBAh)
011471DF 89 4D EC             mov         dword ptr [this],ecx
011471E2 8B 4D EC mov ecx,dword ptr [this]
011471E5 E8 06 B3 FF FF call CBase::CBase (011424F0h) //先调用父类构造函数
011471EA C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
52: CDervie():m_Init(1)
011471F1 6A 01 push 1
011471F3 8B 4D EC mov ecx,dword ptr [this]
011471F6 83 C1 0C add ecx,0Ch //m_Init类成员在类中偏移为0xc,
011471F9 E8 55 CD FF FF call CInit::CInit (01143F53h) //再调用类成员的构造函数,
54: printf("构造列表使用\r\n");
011471FE 68 70 2E 1E 01 push offset string "\xb9\xb9\xd4\xec\xc1\xd0\xb1\xed\xca\xb9\xd3\xc3\r\n" (011E2E70h)
01147203 E8 C2 A1 FF FF call _printf (011413CAh) //最后调用自身构造函数
01147208 83 C4 04 add esp,4
55: }

析构函数

01147661 8D 4D E0             lea         ecx,[Dervie]
01147664 E8 FE B4 FF FF call CDervie::~CDervie (01142B67h)//子类的析构函数 ******************************************************************
CDervie::~CDervie
003F73CF 59 pop ecx
59: ~CDervie() {
003F73D0 89 4D F8 mov dword ptr [this],ecx
60: printf("CDervie析构函数调用\r\n");
003F73D3 68 6C 30 49 00 push offset string "CDervie\xce\xf6\xb9\xb9\xba\xaf\xca\xfd\xb5\xf7\xd3\xc3\r\n" (049306Ch)
003F73D8 E8 ED 9F FF FF call _printf (03F13CAh) //子类先调用自身的析构函数
003F73DD 83 C4 04 add esp,4
61: }
003F73E0 8B 4D F8 mov ecx,dword ptr [this]
003F73E3 83 C1 0C add ecx,0Ch
003F73E6 E8 B7 CC FF FF call CInit::~CInit (03F40A2h) //再调用子类 类成员的析构函数
003F73EB 8B 4D F8 mov ecx,dword ptr [this]
003F73EE E8 8E A2 FF FF call CBase::~CBase (03F1681h) //最后调用父类析构函数

析构顺序与构造顺序正好相反。


  • 单继承,父类存在虚函数,子类重写虚函数,
class CBase
{
public:
CBase()
{
printf("CBase\r\n");
}
~CBase()
{
printf("~CBase\r\n");
}
void SetNumber(int nNumber)
{
m_nBase = nNumber;
}
int GetNumber()
{
return m_nBase;
}
virtual void fun1() { //父类中定义虚函数fun1
printf("CBase fun1\n");
}
virtual void fun2() { //虚函数fun2
printf("CBase fun2\n");
}
public:
int m_nBase;
}; class CDervie : public CBase
{
public:
void ShowNumber(int nNumber)
{
SetNumber(nNumber);
m_nDervie = nNumber + 1;
printf("%d\r\n", GetNumber());
printf("%d\r\n", m_nDervie);
}
void SetNumber(int nNumber){ // 覆盖父类成员方法
m_nBase = nNumber;
}
virtual void fun1() { //子类中重写虚函数。
printf("CDervie fun1\n");
}
CDervie():m_Init(1)
{
printf("构造列表使用\r\n");
}
~CDervie() {
printf("CDervie析构函数调用\r\n");
} public:
int m_nDervie;
int m_nBase; // 覆盖父类数据成员
CInit m_Init; // 初始化列表使用类
};

内存布局

CDervie构造函数

CDervie::CDervie(void)
011371DF 89 4D EC mov dword ptr [this],ecx
011371E2 8B 4D EC mov ecx,dword ptr [this]
011371E5 E8 06 B3 FF FF call CBase::CBase (011324F0h) //先构造父类,因为父类中含虚函数,所以进入后会设置其自身的虚表指针,
011371EA C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
011371F1 8B 45 EC mov eax,dword ptr [this]
011371F4 C7 00 A0 2E 1D 01 mov dword ptr [eax],offset CDervie::`vftable' (011D2EA0h) //设置子类虚表指针
64: CDervie():m_Init(1)
011371FA 6A 01 push 1
011371FC 8B 4D EC mov ecx,dword ptr [this]
011371FF 83 C1 10 add ecx,10h
01137202 E8 4C CD FF FF call CInit::CInit (01133F53h) //类成员构造
66: printf("构造列表使用\r\n");
01137207 68 60 2F 1D 01 push offset string "\xb9\xb9\xd4\xec\xc1\xd0\xb1\xed\xca\xb9\xd3\xc3\r\n" (011D2F60h)
0113720C E8 B9 A1 FF FF call _printf (011313CAh) //子类自身构造
01137211 83 C4 04 add esp,4
67: }

CBase::CBase(void)

0113715F 59                   pop         ecx
01137160 89 4D F8 mov dword ptr [this],ecx
01137163 8B 45 F8 mov eax,dword ptr [this]
01137166 C7 00 60 2E 1D 01 mov dword ptr [eax],offset CBase::`vftable' (011D2E60h) //
23: {
24: printf("CBase\r\n");
0113716C 68 50 2E 1D 01 push offset string "CBase\r\n" (011D2E50h)
01137171 E8 54 A2 FF FF call _printf (011313CAh)
01137176 83 C4 04 add esp,4

CDervie析构函数

CDervie::~CDervie(void)
011373CF 59 pop ecx
011373D0 89 4D F8 mov dword ptr [this],ecx
011373D3 8B 45 F8 mov eax,dword ptr [this]
011373D6 C7 00 A0 2E 1D 01 mov dword ptr [eax],offset CDervie::`vftable' (011D2EA0h) //设置子类自身的虚表指针。
69: printf("CDervie析构函数调用\r\n");
011373DC 68 A8 31 1D 01 push offset string "CDervie\xce\xf6\xb9\xb9\xba\xaf\xca\xfd\xb5\xf7\xd3\xc3\r\n" (011D31A8h)
011373E1 E8 E4 9F FF FF call _printf (011313CAh) //先调用子类析构函数
011373E6 83 C4 04 add esp,4
70: }
011373E9 8B 4D F8 mov ecx,dword ptr [this]
011373EC 83 C1 10 add ecx,10h
011373EF E8 AE CC FF FF call CInit::~CInit (011340A2h) //子类 类成员
011373F4 8B 4D F8 mov ecx,dword ptr [this]
011373F7 E8 85 A2 FF FF call CBase::~CBase (01131681h) //父类,在父类中要设置自身的虚表指针。

CBase::~CBase(void)

0113737F 59                   pop         ecx
01137380 89 4D F8 mov dword ptr [this],ecx
01137383 8B 45 F8 mov eax,dword ptr [this]
01137386 C7 00 60 2E 1D 01 mov dword ptr [eax],offset CBase::`vftable' (011D2E60h) //父类虚表指针。
28: printf("~CBase\r\n");
0113738C 68 70 2E 1D 01 push offset string "~CBase\r\n" (011D2E70h)
01137391 E8 34 A0 FF FF call _printf (011313CAh)
01137396 83 C4 04 add esp,4

  • 单继承,父类存在虚函数,子类不定义虚函数

内存布局


  • 单继承,父类存在虚函数,子类新定义虚函数

此时子类新定义的虚函数,将添加到虚表中。


  • 单继承,父类不存在虚函数,子类定义虚函数

内存布局

  -子类虚表指针

  -父类

  -子类自身数据成员


  • 多继承,父类都有虚函数,子类有重写虚函数
class CBase
{
public:
CBase()
{
printf("CBase\r\n");
}
~CBase()
{
printf("~CBase\r\n");
}
void SetNumber(int nNumber)
{
m_nBase = nNumber;
}
int GetNumber()
{
return m_nBase;
}
virtual void fun1() {
printf("CBase fun1\n");
}
virtual void fun2() {
printf("CBase fun2\n");
}
public:
int m_nBase;
};
class CBase1 { public:
CBase1() {
n_base = 1;
printf("CBase1 构造函数");
}
~CBase1() {
printf("CBase1 构造函数");
}
int n_base;
virtual void fun3() {
printf("CBase1 fun3\n");
}
virtual void fun4() {
printf("CBase1 fun4\n");
}
};
class CDervie : public CBase1,public CBase
{
public:
void ShowNumber(int nNumber)
{
SetNumber(nNumber);
m_nDervie = nNumber + 1;
printf("%d\r\n", GetNumber());
printf("%d\r\n", m_nDervie);
}
void SetNumber(int nNumber){ // 覆盖父类成员方法
m_nBase = nNumber;
}
//virtual void fun1() {
// printf("CDervie fun1\n");
//}
virtual void fun3() {
printf("CDervie fun3\n");
}
CDervie():m_Init(1)
{
printf("构造列表使用\r\n");
}
~CDervie() {
printf("CDervie析构函数调用\r\n");
} public:
int m_nDervie;
int m_nBase; // 覆盖父类数据成员
CInit m_Init; // 初始化列表使用类
};

内存布局

CDervie::CDervie(void)构造函数

0036722F 89 4D EC             mov         dword ptr [this],ecx
00367232 8B 4D EC mov ecx,dword ptr [this]
00367235 E8 90 CE FF FF call CBase1::CBase1 (03640CAh) //构造子类时先按照继承顺序构造父类
85: {
0036723A C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00367241 8B 4D EC mov ecx,dword ptr [this]
00367244 83 C1 08 add ecx,8
00367247 E8 A4 B2 FF FF call CBase::CBase (03624F0h) //继承的第二个父类
0036724C C6 45 FC 01 mov byte ptr [ebp-4],1
00367250 8B 45 EC mov eax,dword ptr [this]
00367253 C7 00 AC 31 40 00 mov dword ptr [eax],offset CDervie::`vftable' (04031ACh) //设置父类1中的虚表指针
00367259 8B 45 EC mov eax,dword ptr [this]
0036725C C7 40 08 80 2E 40 00 mov dword ptr [eax+8],offset CDervie::`vftable' (0402E80h) //设置父类2中的虚表指针
84: CDervie():m_Init(1)
00367263 6A 01 push 1
00367265 8B 4D EC mov ecx,dword ptr [this]
00367268 83 C1 18 add ecx,18h
0036726B E8 E3 CC FF FF call CInit::CInit (0363F53h)
86: printf("构造列表使用\r\n");
00367270 68 78 30 40 00 push offset string "\xb9\xb9\xd4\xec\xc1\xd0\xb1\xed\xca\xb9\xd3\xc3\r\n" (0403078h)
00367275 E8 50 A1 FF FF call _printf (03613CAh)
0036727A 83 C4 04 add esp,4
87: }

CDervie::~CDervie(void)析构函数

0036761F 59                   pop         ecx
00367620 89 4D F8 mov dword ptr [this],ecx
00367623 8B 45 F8 mov eax,dword ptr [this]
00367626 C7 00 AC 31 40 00 mov dword ptr [eax],offset CDervie::`vftable' (04031ACh) //析构先设置虚表指针
0036762C 8B 45 F8 mov eax,dword ptr [this]
0036762F C7 40 08 80 2E 40 00 mov dword ptr [eax+8],offset CDervie::`vftable' (0402E80h)
89: printf("CDervie析构函数调用\r\n");
00367636 68 B4 31 40 00 push offset string "CDervie\xce\xf6\xb9\xb9\xba\xaf\xca\xfd\xb5\xf7\xd3\xc3\r\n" (04031B4h)
0036763B E8 8A 9D FF FF call _printf (03613CAh)
00367640 83 C4 04 add esp,4
90: }
00367643 8B 4D F8 mov ecx,dword ptr [this]
00367646 83 C1 18 add ecx,18h
00367649 E8 54 CA FF FF call CInit::~CInit (03640A2h)
0036764E 8B 4D F8 mov ecx,dword ptr [this]
90: }
00367651 83 C1 08 add ecx,8
00367654 E8 28 A0 FF FF call CBase::~CBase (0361681h) //父类析构与声明顺序相反。
00367659 8B 4D F8 mov ecx,dword ptr [this]
0036765C E8 7D CA FF FF call CBase1::~CBase1 (03640DEh)

  • 多继承,父类1,父类2,其中父类1没有虚函数,父类2有虚函数,子类新定义虚函数

内存布局(一般情况下内存布局按照继承声明的顺序。当父类存在虚函数时,有虚表指针的父类排在前面,并且子类新声明的虚函数添加到虚表后面。)

  -父类2(有虚表)     --虚表{……(子类中如果有重写虚函数,则修改对应表项),(子类新定义的虚函数添加到后面)}

  -父类1(没虚表)

  -子类自身数据成员


  • 多继承,父类中都没有虚函数,子类新定义虚函数

内存布局

  -虚表指针

  -父类1

  -父类2

  -子类自身数据成员


  • 虚基类
// 虚基类分析
class CVirtualBase{
public:
virtual void Show() = 0;
}; class CVirtualChild : public CVirtualBase{
public:
virtual void Show()
{
printf("虚基类分析\r\n");
}
};

内存布局

CVirtualChild VirtualChild;
VirtualChild.Show();

  364:     CVirtualChild VirtualChild;
001DD51A 8D 4D CC lea ecx,[VirtualChild]
001DD51D E8 23 69 FF FF call CVirtualChild::CVirtualChild (01D3E45h)
365: VirtualChild.Show();
001DD522 8D 4D CC lea ecx,[VirtualChild]
001DD525 E8 3A 4A FF FF call CVirtualChild::Show (01D1F64h)

CVirtualChild::CVirtualChild(void)构造函数

001D73FF 59                   pop         ecx
001D7400 89 4D F8 mov dword ptr [this],ecx
001D7403 8B 4D F8 mov ecx,dword ptr [this]
001D7406 E8 A6 B8 FF FF call CVirtualBase::CVirtualBase (01D2CB1h)
001D740B 8B 45 F8 mov eax,dword ptr [this]
001D740E C7 00 F4 3E 27 00 mov dword ptr [eax],offset CVirtualChild::`vftable' (0273EF4h)
001D7414 8B 45 F8 mov eax,dword ptr [this]

CVirtualBase::CVirtualBase(void)构造

001D73AF 59                   pop         ecx
001D73B0 89 4D F8 mov dword ptr [this],ecx
001D73B3 8B 45 F8 mov eax,dword ptr [this]
001D73B6 C7 00 E4 3E 27 00 mov dword ptr [eax],offset CVirtualBase::`vftable' (0273EE4h)
001D73BC 8B 45 F8 mov eax,dword ptr [this]

纯虚函数没有具体实现,CVirtualBase虚表中填入了__purecall函数,防止误用。


  • 菱形继承

class CFurniture{
public:
CFurniture(){
m_nPrice = 0;
}
virtual ~CFurniture(){ // 家具类虚析构函数
printf("virtual ~CFurniture()\r\n");
}
virtual int GetPrice(){ // 获取家具价格
return m_nPrice;
};
protected:
int m_nPrice; // 家具类成员变量
}; // 定义沙发类,继承自CFurniture,等同与类B
class CSofa : virtual public CFurniture{
public:
CSofa(){
m_nPrice = 1;
m_nColor = 2;
}
virtual ~CSofa(){ // 沙发类虚析构函数
printf("virtual ~CSofa()\r\n");
}
virtual int GetColor(){ // 获取沙发颜色
return m_nColor;
}
virtual int SitDown(){ // 沙发可以坐下休息
return printf("Sit down and rest your legs\r\n");
}
protected:
int m_nColor; // 沙发类成员变量
}; // 定义床类,继承自CFurniture,等同与类C
class CBed : virtual public CFurniture{
public:
CBed(){
m_nPrice = 3;
m_nLength = 4;
m_nWidth = 5;
}
virtual ~CBed(){ // 床类虚析构函数
printf("virtual ~CBed()\r\n");
}
virtual int GetArea(){ // 获取床面积
return m_nLength * m_nWidth;
}
virtual int Sleep(){ // 床可以用来睡觉
return printf("go to sleep\r\n");
}
protected:
int m_nLength; // 床类成员变量
int m_nWidth;
}; // 子类沙发床定义,派生自CSofa、CBed类,等同与类D
class CSofaBed : public CSofa, public CBed{
public:
CSofaBed(){
m_nHeight = 6;
}
virtual ~CSofaBed(){ // 沙发床类虚析构函数
printf("virtual ~CSofaBed()\r\n");
}
virtual int SitDown(){ // 沙发可以坐下休息
return printf("Sit down on the sofa bed\r\n");
}
virtual int Sleep(){ // 床可以用来睡觉
return printf("go to sleep on the sofa bed\r\n");
}
virtual int GetHeight(){
return m_nHeight;
}
protected:
int m_nHeight; // 沙发类成员变量
};

// 菱形结构
CSofaBed SofaBed;
CFurniture * pFurniture = &SofaBed;
CSofa * pSofa = &SofaBed;
CBed * pBed = &SofaBed;

内存布局

SofaBed对象中对应的虚表

'-__vfptr 0x00ed3eb0 {ClassRelation.exe!void(* CSofaBed::`vftable'[4])()} 

[0x00000000] 0x00e340ed {ClassRelation.exe!CSofa::GetColor(void)}

[0x00000001] 0x00e34129 {ClassRelation.exe!CSofaBed::SitDown(void)}

[0x00000002] 0x00e34138 {ClassRelation.exe!CSofaBed::GetHeight(void)} (子类中新定义的虚函数,添加到了第一个虚表中)

offset_ptr1 (指向一表,第一项为offset_ptr1到所属类虚表指针的偏移,第二项为到父类虚表指针的偏移)

0x00ED3EBC  fc ff ff ff

0x00ED3EC0  1c 00 00 00

'- __vfptr 0x00ed3e88 {ClassRelation.exe!void(* CSofaBed::`vftable'[3])()}
[0x00000000] 0x00e3411f {ClassRelation.exe!CBed::GetArea(void)} void *
[0x00000001] 0x00e3410b {ClassRelation.exe!CSofaBed::Sleep(void)} void *

0x00ED3EE8  fc ff ff ff

0x00ED3EEC  10 00 00 00

'- __vfptr 0x00ed3ed4 {ClassRelation.exe!void(* CSofaBed::`vftable'[3])()}
[0x00000000] 0x00e340e8 {ClassRelation.exe!CSofaBed::`vector deleting destructor'(unsigned int)} void *
[0x00000001] 0x00e3413d {ClassRelation.exe!CFurniture::GetPrice(void)} void *

汇编

 368:     // 菱形结构
369: CSofaBed SofaBed;
00E3A8CE 6A 01 push 1 //是否构造祖父类标志,
00E3A8D0 8D 4D D4 lea ecx,[SofaBed]
00E3A8D3 E8 06 98 FF FF call CSofaBed::CSofaBed (0E340DEh)
370: CFurniture * pFurniture = &SofaBed;
00E3A8D8 8D 45 D4 lea eax,[SofaBed]
00E3A8DB 85 C0 test eax,eax //检查对象是否构造成功
00E3A8DD 75 0C jne main+3Bh (0E3A8EBh)
00E3A8DF C7 85 E8 FE FF FF 00 00 00 00 mov dword ptr [ebp-118h],0
00E3A8E9 EB 10 jmp main+4Bh (0E3A8FBh)
00E3A8EB 8B 4D D8 mov ecx,dword ptr [ebp-28h] //SofaBed对象的第二项,对应CSofa类的偏移指针
00E3A8EE 8B 51 04 mov edx,dword ptr [ecx+4] //取得CSofa的父类,即CFurniture偏移量
00E3A8F1 8D 44 15 D8 lea eax,[ebp+edx-28h] //根据偏移量,得到CFurniture在内存布局中的相对位置地址
00E3A8F5 89 85 E8 FE FF FF mov dword ptr [ebp-118h],eax //局部变量转存
00E3A8FB 8B 8D E8 FE FF FF mov ecx,dword ptr [ebp-118h]
00E3A901 89 4D C8 mov dword ptr [pFurniture],ecx
371: CSofa * pSofa = &SofaBed;
00E3A904 8D 45 D4 lea eax,[SofaBed] //CSofa在对象SofaBed内存布局中排在第一项
371: CSofa * pSofa = &SofaBed;
00E3A907 89 45 BC mov dword ptr [pSofa],eax
372: CBed * pBed = &SofaBed;
00E3A90A 8D 45 D4 lea eax,[SofaBed]
00E3A90D 85 C0 test eax,eax
00E3A90F 74 0E je main+6Fh (0E3A91Fh)
00E3A911 8D 4D D4 lea ecx,[SofaBed]
00E3A914 83 C1 0C add ecx,0Ch //CBed在对象中偏移位0xc
00E3A917 89 8D E8 FE FF FF mov dword ptr [ebp-118h],ecx
00E3A91D EB 0A jmp main+79h (0E3A929h)
00E3A91F C7 85 E8 FE FF FF 00 00 00 00 mov dword ptr [ebp-118h],0
00E3A929 8B 95 E8 FE FF FF mov edx,dword ptr [ebp-118h]
00E3A92F 89 55 B0 mov dword ptr [pBed],edx
373: }

CSofaBed::CSofaBed(void)构造函数

 310:     CSofaBed(){
00E42CA2 C7 85 20 FF FF FF 00 00 00 00 mov dword ptr [ebp-0E0h],0 //设置构造标志
00E42CAC 83 7D 08 00 cmp dword ptr [ebp+8],0 //判断祖父类构造标志
00E42CB0 74 35 je CSofaBed::CSofaBed+87h (0E42CE7h)
00E42CB2 8B 45 EC mov eax,dword ptr [this]
00E42CB5 C7 40 04 BC 3E ED 00 mov dword ptr [eax+4],offset CSofaBed::`vbtable' (0ED3EBCh) //设置CSofa的偏移指针
00E42CBC 8B 45 EC mov eax,dword ptr [this]
00E42CBF C7 40 10 E8 3E ED 00 mov dword ptr [eax+10h],offset CSofaBed::`vbtable' (0ED3EE8h) //设置CBed的偏移指针
00E42CC6 8B 4D EC mov ecx,dword ptr [this]
00E42CC9 83 C1 20 add ecx,20h
00E42CCC E8 62 14 FF FF call CFurniture::CFurniture (0E34133h)
00E42CD1 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00E42CD8 8B 85 20 FF FF FF mov eax,dword ptr [ebp-0E0h]
00E42CDE 83 C8 01 or eax,1 //构造标志置1
00E42CE1 89 85 20 FF FF FF mov dword ptr [ebp-0E0h],eax
00E42CE7 6A 00 push 0 //压入0作为构造标志
00E42CE9 8B 4D EC mov ecx,dword ptr [this]
00E42CEC E8 CF 13 FF FF call CSofa::CSofa (0E340C0h) //CSofa构造
00E42CF1 C7 45 FC 01 00 00 00 mov dword ptr [ebp-4],1
00E42CF8 6A 00 push 0 //压入0作为构造标志
00E42CFA 8B 4D EC mov ecx,dword ptr [this]
00E42CFD 83 C1 0C add ecx,0Ch
00E42D00 E8 D4 13 FF FF call CBed::CBed (0E340D9h) //CBed构造
00E42D05 8B 45 EC mov eax,dword ptr [this]
00E42D08 C7 00 B0 3E ED 00 mov dword ptr [eax],offset CSofaBed::`vftable' (0ED3EB0h) //设置CSofaBed对应的CSofa虚表指针
00E42D0E 8B 45 EC mov eax,dword ptr [this]
00E42D11 C7 40 0C 88 3E ED 00 mov dword ptr [eax+0Ch],offset CSofaBed::`vftable' (0ED3E88h) //设置CSofaBed对应的CBed虚表指针
00E42D18 8B 45 EC mov eax,dword ptr [this]
00E42D1B 8B 48 04 mov ecx,dword ptr [eax+4] //取CSofa的偏移指针
00E42D1E 8B 51 04 mov edx,dword ptr [ecx+4] //取偏移表的第二项,即到其父类CFurniture的偏移。
00E42D21 8B 45 EC mov eax,dword ptr [this]
00E42D24 C7 44 10 04 D4 3E ED 00 mov dword ptr [eax+edx+4],offset CSofaBed::`vftable' (0ED3ED4h) //设置CSofaBed对应的CFurniture的虚表指针
311: m_nHeight = 6;
00E42D2C 8B 45 EC mov eax,dword ptr [this]
00E42D2F C7 40 1C 06 00 00 00 mov dword ptr [eax+1Ch],6
312: }

函数

CSofa::CSofa:
00E340C0 E9 9B 31 00 00 jmp CSofa::CSofa (0E37260h)
CSofa::`vector deleting destructor':
00E340C5 E9 36 40 00 00 jmp CSofa::`scalar deleting destructor' (0E38100h)
CFurniture::`vector deleting destructor':
00E340CA E9 D1 35 00 00 jmp CFurniture::`scalar deleting destructor' (0E376A0h)
CSofa::`vbase destructor':
00E340CF E9 BC 34 00 00 jmp CSofa::`vbase destructor' (0E37590h)
CBed::`vbase destructor':
00E340D4 E9 27 34 00 00 jmp CBed::`vbase destructor' (0E37500h)
CBed::CBed:
00E340D9 E9 F2 37 00 00 jmp CBed::CBed (0E378D0h)
CSofaBed::CSofaBed:
00E340DE E9 7D EB 00 00 jmp CSofaBed::CSofaBed (0E42C60h)
CSofaBed::`vector deleting destructor':
00E340E3 E9 18 36 00 00 jmp CSofaBed::`scalar deleting destructor' (0E37700h)
CSofaBed::`vector deleting destructor':
00E340E8 E9 13 36 00 00 jmp CSofaBed::`scalar deleting destructor' (0E37700h)
CSofa::GetColor:
00E340ED E9 AE 93 00 00 jmp CSofa::GetColor (0E3D4A0h)
CSofa::`vector deleting destructor':
00E340F2 E9 09 40 00 00 jmp CSofa::`scalar deleting destructor' (0E38100h)
CFurniture::~CFurniture:
00E340F7 E9 E4 32 00 00 jmp CFurniture::~CFurniture (0E373E0h)
CFurniture::`vector deleting destructor':
00E340FC E9 9F 35 00 00 jmp CFurniture::`scalar deleting destructor' (0E376A0h)
CBed::Sleep:
00E34101 E9 3A 35 00 00 jmp CBed::Sleep (0E37640h)
CSofaBed::~CSofaBed:
00E34106 E9 85 38 00 00 jmp CSofaBed::~CSofaBed (0E37990h)
CSofaBed::Sleep:
00E3410B E9 60 36 00 00 jmp CSofaBed::Sleep (0E37770h)
CBed::`vector deleting destructor':
00E34110 E9 0B 39 00 00 jmp CBed::`scalar deleting destructor' (0E37A20h)
CSofa::SitDown:
00E34115 E9 66 32 00 00 jmp CSofa::SitDown (0E37380h)
CSofa::~CSofa:
00E3411A E9 11 33 00 00 jmp CSofa::~CSofa (0E37430h)
CBed::GetArea:
00E3411F E9 9C 36 00 00 jmp CBed::GetArea (0E377C0h)
CSofaBed::`vbase destructor':
00E34124 E9 C7 34 00 00 jmp CSofaBed::`vbase destructor' (0E375F0h)
CSofaBed::SitDown:
00E34129 E9 72 33 00 00 jmp CSofaBed::SitDown (0E374A0h)
CBed::~CBed:
00E3412E E9 DD 31 00 00 jmp CBed::~CBed (0E37310h)
CFurniture::CFurniture:
00E34133 E9 B8 30 00 00 jmp CFurniture::CFurniture (0E371F0h)
CSofaBed::GetHeight:
00E34138 E9 23 37 00 00 jmp CSofaBed::GetHeight (0E37860h)
CFurniture::GetPrice:
00E3413D E9 EE 30 00 00 jmp CFurniture::GetPrice (0E37230h)
CBed::`vector deleting destructor':
00E34142 E9 D9 38 00 00 jmp CBed::`scalar deleting destructor' (0E37A20h)

c++ 反汇编 继承的更多相关文章

  1. C++反汇编-继承和多重继承

    学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然 ...

  2. C++反汇编与逆向分析技术揭秘

    C++反汇编-继承和多重继承   学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的 ...

  3. C++反汇编第四讲,反汇编中识别继承关系,父类,子类,成员对象

    C++反汇编第四讲,反汇编中识别继承关系,父类,子类,成员对象 讲解目录: 1.各类在内存中的表现形式   备注: 主要复习开发知识,和反汇编没有关系,但是是理解反汇编的前提.     2.子类继承父 ...

  4. C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.

    C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式. 目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形 ...

  5. C++反汇编-菱形继承

    学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记.马上就要出差了,回来后接着写吧. 一.概述 菱形继承是最复杂的对象结构,菱形结构会将单一继承与多重继承进行组合. ...

  6. C++反汇编第四讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.

    目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形式 一丶多重继承在内存中的表现形式 高级代码: class Father1 { ...

  7. C++反汇编第三讲,反汇编中识别继承关系,父类,子类,成员对象

    讲解目录: 1.各类在内存中的表现形式   备注: 主要复习开发知识,和反汇编没有关系,但是是理解反汇编的前提.     2.子类继承父类 2.1 子类中有虚函数,父类中有虚函数 : 都有的情况下   ...

  8. 《C++反汇编与逆向分析技术揭秘》之12——继承

    识别类和类之间的关系 在父类中声明为私有的成员,虽然子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在. 在没有提供构造函数的时候,系统会尝试提供默认的构造函数: 当子类中没 ...

  9. 内存角度探寻C++面向对象 之 继承、多态

    一,简单继承: #include <iostream> class TableTennisPlayer { private: int id; public: TableTennisPlay ...

随机推荐

  1. 如何在Python 中使用UTF-8 编码 && Python 使用 注释,Python ,UTF-8 编码 , Python 注释

    如何在Python 中使用UTF-8 编码 && Python 使用 注释,Python ,UTF-8 编码 , Python  注释 PIP $ pip install beauti ...

  2. node.js 中间件

    node.js 中间件 node.js middleware Express middleware body-parser cookie-parser cookie-session cors csur ...

  3. Microsoft Lifecycle Policy

    Microsoft Lifecycle Policy The Microsoft Lifecycle Policy gives you consistent and predictable guide ...

  4. html5 useful skills blogs

    html5 useful skills blogs preload & prefetch https://www.30secondsofcode.org/snippet/ary blogs h ...

  5. SPC算力空投来袭!对话NGK!华盛顿金融特别报道

    近日华盛顿金融时报联合波士顿商业报等多家知名金融媒体专访了NGK. NGK代表马特彼得森就表示NGK在新的一年里将会继续以生态建设者为中心,以打造高倍币孵化器为目标,不断推进NGK项目的落地,踏踏实实 ...

  6. Baccarat流动性挖矿的收益能否持续?该如何参与Baccarat流动性挖矿?

    2020年DeFi市场火热,众多投资机构纷纷入场,分享这场资本盛宴.然而,目前市面上大多数DeFi项目手续费高昂,小资金的投资者无法入市.为了让更多的用户参与其中,NGK推出了Baccarat流动性挖 ...

  7. 云服务器Centos7部署Tomcat服务器

    目录 部署Tomcat服务器 1.安装JDK1.8 2.安装与启动tomcat 配置安全组(8080端口) 参考文章 部署Tomcat服务器 1.安装JDK1.8 JDK下载地址:https://ww ...

  8. FTP服务器搭建以及上传下载的学习

    首先需要搭建FTP服务步骤如下: 1.在win7上先开启ftp服务:这里点击确定后,可能会要等一会儿,完成后有时系统会提示重启 2.打开   计算机-->管理-->   在这里我们可以看见 ...

  9. Jquery获取链接请求的参数

    比如有一个链接:https://www.baidu.com/s?cl=3&tn=baidutop10&fr=top1000,先定义方法: //获取url中的参数 function ge ...

  10. Ajax的基本用法

    1.介绍 2.基本用法 2.1原生写法 $.ajax({ url: url, //是否是异步请求,默认是 // async: false, //请求方式,默认是get //type:'get', // ...