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

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

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

};

  1. class CBase
  2. {
  3. public:
  4. CBase()
  5. {
  6. printf("CBase\r\n");
  7. }
  8. ~CBase()
  9. {
  10. printf("~CBase\r\n");
  11. }
  12. void SetNumber(int nNumber)
  13. {
  14. m_nBase = nNumber;
  15. }
  16. int GetNumber()
  17. {
  18. return m_nBase;
  19. }
  20. public:
  21. int m_nBase;
  22. };
  23.  
  24. class CDervie : public CBase
  25. {
  26. public:
  27. void ShowNumber(int nNumber)
  28. {
  29. SetNumber(nNumber);
  30. m_nDervie = nNumber + 1;
  31. printf("%d\r\n", GetNumber());
  32. printf("%d\r\n", m_nDervie);
  33. }
  34. void SetNumber(int nNumber){ // 覆盖父类成员方法
  35. m_nBase = nNumber;
  36. }
  37. CDervie():m_Init(1)
  38. {
  39. printf("构造列表使用\r\n");
  40. }
       ~CDervie() {

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

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

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

  1. void main(int argc, char* argv[])
  2. {
  3.  
  4. CDervie Dervie;
  5. Dervie.SetNumber(argc);
  6. printf("%d\r\n", Dervie.m_nBase);
  7. printf("%d\r\n", Dervie.CBase::m_nBase);
  8. }

内存布局

汇编

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

构造函数

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

析构函数

  1. 01147661 8D 4D E0 lea ecx,[Dervie]
  2. 01147664 E8 FE B4 FF FF call CDervie::~CDervie (01142B67h)//子类的析构函数
  3.  
  4. ******************************************************************
  1. CDervie::~CDervie
  2. 003F73CF 59 pop ecx
  3. 59: ~CDervie() {
  4. 003F73D0 89 4D F8 mov dword ptr [this],ecx
  5. 60: printf("CDervie析构函数调用\r\n");
  6. 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)
  7. 003F73D8 E8 ED 9F FF FF call _printf (03F13CAh) //子类先调用自身的析构函数
  8. 003F73DD 83 C4 04 add esp,4
  9. 61: }
  10. 003F73E0 8B 4D F8 mov ecx,dword ptr [this]
  11. 003F73E3 83 C1 0C add ecx,0Ch
  12. 003F73E6 E8 B7 CC FF FF call CInit::~CInit (03F40A2h) //再调用子类 类成员的析构函数
  13. 003F73EB 8B 4D F8 mov ecx,dword ptr [this]
  14. 003F73EE E8 8E A2 FF FF call CBase::~CBase (03F1681h) //最后调用父类析构函数

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


  • 单继承,父类存在虚函数,子类重写虚函数,
  1. class CBase
  2. {
  3. public:
  4. CBase()
  5. {
  6. printf("CBase\r\n");
  7. }
  8. ~CBase()
  9. {
  10. printf("~CBase\r\n");
  11. }
  12. void SetNumber(int nNumber)
  13. {
  14. m_nBase = nNumber;
  15. }
  16. int GetNumber()
  17. {
  18. return m_nBase;
  19. }
  20. virtual void fun1() { //父类中定义虚函数fun1
  21. printf("CBase fun1\n");
  22. }
  23. virtual void fun2() { //虚函数fun2
  24. printf("CBase fun2\n");
  25. }
  26. public:
  27. int m_nBase;
  28. };
  29.  
  30. class CDervie : public CBase
  31. {
  32. public:
  33. void ShowNumber(int nNumber)
  34. {
  35. SetNumber(nNumber);
  36. m_nDervie = nNumber + 1;
  37. printf("%d\r\n", GetNumber());
  38. printf("%d\r\n", m_nDervie);
  39. }
  40. void SetNumber(int nNumber){ // 覆盖父类成员方法
  41. m_nBase = nNumber;
  42. }
  43. virtual void fun1() { //子类中重写虚函数。
  44. printf("CDervie fun1\n");
  45. }
  46. CDervie():m_Init(1)
  47. {
  48. printf("构造列表使用\r\n");
  49. }
  50. ~CDervie() {
  51. printf("CDervie析构函数调用\r\n");
  52. }
  53.  
  54. public:
  55. int m_nDervie;
  56. int m_nBase; // 覆盖父类数据成员
  57. CInit m_Init; // 初始化列表使用类
  58. };

内存布局

CDervie构造函数

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

CBase::CBase(void)

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

CDervie析构函数

  1. CDervie::~CDervie(void)
  2. 011373CF 59 pop ecx
  3. 011373D0 89 4D F8 mov dword ptr [this],ecx
  4. 011373D3 8B 45 F8 mov eax,dword ptr [this]
  5. 011373D6 C7 00 A0 2E 1D 01 mov dword ptr [eax],offset CDervie::`vftable' (011D2EA0h) //设置子类自身的虚表指针。
  6. 69: printf("CDervie析构函数调用\r\n");
  7. 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)
  8. 011373E1 E8 E4 9F FF FF call _printf (011313CAh) //先调用子类析构函数
  9. 011373E6 83 C4 04 add esp,4
  10. 70: }
  11. 011373E9 8B 4D F8 mov ecx,dword ptr [this]
  12. 011373EC 83 C1 10 add ecx,10h
  13. 011373EF E8 AE CC FF FF call CInit::~CInit (011340A2h) //子类 类成员
  14. 011373F4 8B 4D F8 mov ecx,dword ptr [this]
  15. 011373F7 E8 85 A2 FF FF call CBase::~CBase (01131681h) //父类,在父类中要设置自身的虚表指针。

CBase::~CBase(void)

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

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

内存布局


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

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


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

内存布局

  -子类虚表指针

  -父类

  -子类自身数据成员


  • 多继承,父类都有虚函数,子类有重写虚函数
  1. class CBase
  2. {
  3. public:
  4. CBase()
  5. {
  6. printf("CBase\r\n");
  7. }
  8. ~CBase()
  9. {
  10. printf("~CBase\r\n");
  11. }
  12. void SetNumber(int nNumber)
  13. {
  14. m_nBase = nNumber;
  15. }
  16. int GetNumber()
  17. {
  18. return m_nBase;
  19. }
  20. virtual void fun1() {
  21. printf("CBase fun1\n");
  22. }
  23. virtual void fun2() {
  24. printf("CBase fun2\n");
  25. }
  26. public:
  27. int m_nBase;
  28. };
  29. class CBase1 {
  30.  
  31. public:
  32. CBase1() {
  33. n_base = 1;
  34. printf("CBase1 构造函数");
  35. }
  36. ~CBase1() {
  37. printf("CBase1 构造函数");
  38. }
  39. int n_base;
  40. virtual void fun3() {
  41. printf("CBase1 fun3\n");
  42. }
  43. virtual void fun4() {
  44. printf("CBase1 fun4\n");
  45. }
  46. };
  47. class CDervie : public CBase1,public CBase
  48. {
  49. public:
  50. void ShowNumber(int nNumber)
  51. {
  52. SetNumber(nNumber);
  53. m_nDervie = nNumber + 1;
  54. printf("%d\r\n", GetNumber());
  55. printf("%d\r\n", m_nDervie);
  56. }
  57. void SetNumber(int nNumber){ // 覆盖父类成员方法
  58. m_nBase = nNumber;
  59. }
  60. //virtual void fun1() {
  61. // printf("CDervie fun1\n");
  62. //}
  63. virtual void fun3() {
  64. printf("CDervie fun3\n");
  65. }
  66. CDervie():m_Init(1)
  67. {
  68. printf("构造列表使用\r\n");
  69. }
  70. ~CDervie() {
  71. printf("CDervie析构函数调用\r\n");
  72. }
  73.  
  74. public:
  75. int m_nDervie;
  76. int m_nBase; // 覆盖父类数据成员
  77. CInit m_Init; // 初始化列表使用类
  78. };

内存布局

CDervie::CDervie(void)构造函数

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

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

  1. 0036761F 59 pop ecx
  2. 00367620 89 4D F8 mov dword ptr [this],ecx
  3. 00367623 8B 45 F8 mov eax,dword ptr [this]
  4. 00367626 C7 00 AC 31 40 00 mov dword ptr [eax],offset CDervie::`vftable' (04031ACh) //析构先设置虚表指针
  5. 0036762C 8B 45 F8 mov eax,dword ptr [this]
  6. 0036762F C7 40 08 80 2E 40 00 mov dword ptr [eax+8],offset CDervie::`vftable' (0402E80h)
  7. 89: printf("CDervie析构函数调用\r\n");
  8. 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)
  9. 0036763B E8 8A 9D FF FF call _printf (03613CAh)
  10. 00367640 83 C4 04 add esp,4
  11. 90: }
  12. 00367643 8B 4D F8 mov ecx,dword ptr [this]
  13. 00367646 83 C1 18 add ecx,18h
  14. 00367649 E8 54 CA FF FF call CInit::~CInit (03640A2h)
  15. 0036764E 8B 4D F8 mov ecx,dword ptr [this]
  16. 90: }
  17. 00367651 83 C1 08 add ecx,8
  18. 00367654 E8 28 A0 FF FF call CBase::~CBase (0361681h) //父类析构与声明顺序相反。
  19. 00367659 8B 4D F8 mov ecx,dword ptr [this]
  20. 0036765C E8 7D CA FF FF call CBase1::~CBase1 (03640DEh)

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

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

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

  -父类1(没虚表)

  -子类自身数据成员


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

内存布局

  -虚表指针

  -父类1

  -父类2

  -子类自身数据成员


  • 虚基类
  1. // 虚基类分析
  2. class CVirtualBase{
  3. public:
  4. virtual void Show() = 0;
  5. };
  6.  
  7. class CVirtualChild : public CVirtualBase{
  8. public:
  9. virtual void Show()
  10. {
  11. printf("虚基类分析\r\n");
  12. }
  13. };

内存布局

CVirtualChild VirtualChild;
VirtualChild.Show();

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

CVirtualChild::CVirtualChild(void)构造函数

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

CVirtualBase::CVirtualBase(void)构造

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

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


  • 菱形继承

  1. class CFurniture{
  2. public:
  3. CFurniture(){
  4. m_nPrice = 0;
  5. }
  6. virtual ~CFurniture(){ // 家具类虚析构函数
  7. printf("virtual ~CFurniture()\r\n");
  8. }
  9. virtual int GetPrice(){ // 获取家具价格
  10. return m_nPrice;
  11. };
  12. protected:
  13. int m_nPrice; // 家具类成员变量
  14. };
  15.  
  16. // 定义沙发类,继承自CFurniture,等同与类B
  17. class CSofa : virtual public CFurniture{
  18. public:
  19. CSofa(){
  20. m_nPrice = 1;
  21. m_nColor = 2;
  22. }
  23. virtual ~CSofa(){ // 沙发类虚析构函数
  24. printf("virtual ~CSofa()\r\n");
  25. }
  26. virtual int GetColor(){ // 获取沙发颜色
  27. return m_nColor;
  28. }
  29. virtual int SitDown(){ // 沙发可以坐下休息
  30. return printf("Sit down and rest your legs\r\n");
  31. }
  32. protected:
  33. int m_nColor; // 沙发类成员变量
  34. };
  35.  
  36. // 定义床类,继承自CFurniture,等同与类C
  37. class CBed : virtual public CFurniture{
  38. public:
  39. CBed(){
  40. m_nPrice = 3;
  41. m_nLength = 4;
  42. m_nWidth = 5;
  43. }
  44. virtual ~CBed(){ // 床类虚析构函数
  45. printf("virtual ~CBed()\r\n");
  46. }
  47. virtual int GetArea(){ // 获取床面积
  48. return m_nLength * m_nWidth;
  49. }
  50. virtual int Sleep(){ // 床可以用来睡觉
  51. return printf("go to sleep\r\n");
  52. }
  53. protected:
  54. int m_nLength; // 床类成员变量
  55. int m_nWidth;
  56. };
  57.  
  58. // 子类沙发床定义,派生自CSofa、CBed类,等同与类D
  59. class CSofaBed : public CSofa, public CBed{
  60. public:
  61. CSofaBed(){
  62. m_nHeight = 6;
  63. }
  64. virtual ~CSofaBed(){ // 沙发床类虚析构函数
  65. printf("virtual ~CSofaBed()\r\n");
  66. }
  67. virtual int SitDown(){ // 沙发可以坐下休息
  68. return printf("Sit down on the sofa bed\r\n");
  69. }
  70. virtual int Sleep(){ // 床可以用来睡觉
  71. return printf("go to sleep on the sofa bed\r\n");
  72. }
  73. virtual int GetHeight(){
  74. return m_nHeight;
  75. }
  76. protected:
  77. int m_nHeight; // 沙发类成员变量
  78. };

// 菱形结构
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 *

汇编

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

CSofaBed::CSofaBed(void)构造函数

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

函数

  1. CSofa::CSofa:
  2. 00E340C0 E9 9B 31 00 00 jmp CSofa::CSofa (0E37260h)
  3. CSofa::`vector deleting destructor':
  4. 00E340C5 E9 36 40 00 00 jmp CSofa::`scalar deleting destructor' (0E38100h)
  5. CFurniture::`vector deleting destructor':
  6. 00E340CA E9 D1 35 00 00 jmp CFurniture::`scalar deleting destructor' (0E376A0h)
  7. CSofa::`vbase destructor':
  8. 00E340CF E9 BC 34 00 00 jmp CSofa::`vbase destructor' (0E37590h)
  9. CBed::`vbase destructor':
  10. 00E340D4 E9 27 34 00 00 jmp CBed::`vbase destructor' (0E37500h)
  11. CBed::CBed:
  12. 00E340D9 E9 F2 37 00 00 jmp CBed::CBed (0E378D0h)
  13. CSofaBed::CSofaBed:
  14. 00E340DE E9 7D EB 00 00 jmp CSofaBed::CSofaBed (0E42C60h)
  15. CSofaBed::`vector deleting destructor':
  16. 00E340E3 E9 18 36 00 00 jmp CSofaBed::`scalar deleting destructor' (0E37700h)
  17. CSofaBed::`vector deleting destructor':
  18. 00E340E8 E9 13 36 00 00 jmp CSofaBed::`scalar deleting destructor' (0E37700h)
  19. CSofa::GetColor:
  20. 00E340ED E9 AE 93 00 00 jmp CSofa::GetColor (0E3D4A0h)
  21. CSofa::`vector deleting destructor':
  22. 00E340F2 E9 09 40 00 00 jmp CSofa::`scalar deleting destructor' (0E38100h)
  23. CFurniture::~CFurniture:
  24. 00E340F7 E9 E4 32 00 00 jmp CFurniture::~CFurniture (0E373E0h)
  25. CFurniture::`vector deleting destructor':
  26. 00E340FC E9 9F 35 00 00 jmp CFurniture::`scalar deleting destructor' (0E376A0h)
  27. CBed::Sleep:
  28. 00E34101 E9 3A 35 00 00 jmp CBed::Sleep (0E37640h)
  29. CSofaBed::~CSofaBed:
  30. 00E34106 E9 85 38 00 00 jmp CSofaBed::~CSofaBed (0E37990h)
  31. CSofaBed::Sleep:
  32. 00E3410B E9 60 36 00 00 jmp CSofaBed::Sleep (0E37770h)
  33. CBed::`vector deleting destructor':
  34. 00E34110 E9 0B 39 00 00 jmp CBed::`scalar deleting destructor' (0E37A20h)
  35. CSofa::SitDown:
  36. 00E34115 E9 66 32 00 00 jmp CSofa::SitDown (0E37380h)
  37. CSofa::~CSofa:
  38. 00E3411A E9 11 33 00 00 jmp CSofa::~CSofa (0E37430h)
  39. CBed::GetArea:
  40. 00E3411F E9 9C 36 00 00 jmp CBed::GetArea (0E377C0h)
  41. CSofaBed::`vbase destructor':
  42. 00E34124 E9 C7 34 00 00 jmp CSofaBed::`vbase destructor' (0E375F0h)
  43. CSofaBed::SitDown:
  44. 00E34129 E9 72 33 00 00 jmp CSofaBed::SitDown (0E374A0h)
  45. CBed::~CBed:
  46. 00E3412E E9 DD 31 00 00 jmp CBed::~CBed (0E37310h)
  47. CFurniture::CFurniture:
  48. 00E34133 E9 B8 30 00 00 jmp CFurniture::CFurniture (0E371F0h)
  49. CSofaBed::GetHeight:
  50. 00E34138 E9 23 37 00 00 jmp CSofaBed::GetHeight (0E37860h)
  51. CFurniture::GetPrice:
  52. 00E3413D E9 EE 30 00 00 jmp CFurniture::GetPrice (0E37230h)
  53. CBed::`vector deleting destructor':
  54. 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. How To Install Linux & Nginx & MySQL & PHP (LEMP) stack on Raspberry Pi 3,Raspberry Pi 3,LEMP,Nginx,PHP, LEMP (not LNMP)

    1.   How To Install Linux & Nginx & MySQL & PHP (LEMP) stack on Raspberry Pi 3         R ...

  2. how to updating Node.js and npm

    how to updating  Node.js and npm 1 Installing Node.js and updating npm How do I update Node.js ? Not ...

  3. DataBase All in One

    DataBase All in One DB SQL: relational database management system NoSQL(Not only SQL / Non SQL): key ...

  4. GitHub 500 error

    GitHub 500 error 无法访问了, GitHub 挂了又! error reports Downdetector Github down? Current service status a ...

  5. 1月加密货币交易所访问量破3亿!NGK生态星空计划、NGK生态所带来双重利好!

    据最新数据显示,2021年一月份,加密货币交易所网站的访问量急剧上升.约有3.44亿访问者涌入了加密货币交易所,超过2020年12月的1.96亿访问者总数,创2018年1月以来新高. 加密货币交易所网 ...

  6. vue最好的ssr服务器渲染框架

    vue和angular js.react三大框架非常好用,现在大部分人都使用了这三大框架进行开发. 但是vue这些框架到目前位置,大部分还是用来做管理后台,用来做移动端.而官网网站却很少用他们来开发. ...

  7. K8S部署Redis Cluster集群(三主三从模式) - 部署笔记

    一.Redis 介绍 Redis代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理.它可以存储和操作高级数据类型,例如列表,地图,集合和排序 ...

  8. 深入理解Linux TCP backlog

    本文转载自深入理解Linux TCP backlog 当应用程序调用listen系统调用让一个socket进入LISTEN状态时,需要指定一个参数:backlog.这个参数经常被描述为,新连接队列的长 ...

  9. banner自用图床

    放些常用的图做图床,也不在别的平台用.

  10. 数理统计16:NP理论、似然比检验、假设检验与区间估计

    本文介绍Neyman-Pearson理论,这也是我们会见到的最常见假设检验问题类,这里第一Part的概念介绍略显枯燥,大家尽量理解即可.由于本系列为我独自完成的,缺少审阅,如果有任何错误,欢迎在评论区 ...