用汇编的眼光看C++(之类继承)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/feixiaoxing/article/details/6775676

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    继承是类的一个基本属性,可是在类的继承过程中,函数是怎么初始化?怎么析构的呢?我们不妨看看下面这样的一段代码?


 
 
  1. class employee
  2. {
  3. public:
  4. employee() { printf( "employee()!\n");}
  5. ~employee() { printf( "~employee()!\n");}
  6. };
  7. class manager : public employee
  8. {
  9. public:
  10. manager() { printf( "manager()!\n");}
  11. ~manager() { printf( "~maneger()!\n");}
  12. };
    看到上面的代码,相信大家也明白了,我们定义了这样一个类。基类是empoyee,继承类是manager。我们看到manager是一种特殊的employee,那么在内存构建和析构的时候函数又是怎么安排的呢?


 
 
  1. 74: manager m;
  2. 00401268 lea ecx,[ebp- 4]
  3. 0040126B call @ILT+ 60(manager::manager) ( 00401041)
  4. 75: }
  5. 00401270 lea ecx,[ebp- 4]
  6. 00401273 call @ILT+ 0(manager::~manager) ( 00401005)
  7. 00401278 pop edi
  8. 00401279 pop esi
  9. 0040127A pop ebx
  10. 0040127B add esp, 44h
  11. 0040127E cmp ebp,esp
  12. 0040128 0 call __chkesp ( 0040876 0)
  13. 00401285 mov esp,ebp
  14. 00401287 pop ebp
    我们发现manager的构造和析构其实也简单。构造函数其实就是在变量出现的时候进行构造。那什么时候析构呢?也就在函数快结束的时候进行析构。下面我们可以进一步讨论在manager的构造和析构究竟是怎么做的?


 
 
  1. 65: class manager : public employee
  2. 66: {
  3. 67: public:
  4. 68: manager() { printf( "manager()!\n");}
  5. 004012A0 push ebp
  6. 004012A1 mov ebp,esp
  7. 004012A3 sub esp, 44h
  8. 004012A6 push ebx
  9. 004012A7 push esi
  10. 004012A8 push edi
  11. 004012A9 push ecx
  12. 004012AA lea edi,[ebp -44h]
  13. 004012AD mov ecx, 11h
  14. 004012B2 mov eax, 0CCCCCCCCh
  15. 004012B7 rep stos dword ptr [edi]
  16. 004012B9 pop ecx
  17. 004012BA mov dword ptr [ebp -4],ecx
  18. 004012BD mov ecx,dword ptr [ebp -4]
  19. 004012C0 call @ILT+ 40(employee::employee) ( 0040102d)
  20. 004012C5 push offset string "manager()!\n" ( 00431020)
  21. 004012CA call printf ( 004086e0)
  22. 004012CF add esp, 4
  23. 004012D2 mov eax,dword ptr [ebp -4]
  24. 004012D5 pop edi
  25. 004012D6 pop esi
  26. 004012D7 pop ebx
  27. 004012D8 add esp, 44h
  28. 004012DB cmp ebp,esp
  29. 004012DD call __chkesp ( 00408760)
  30. 004012E2 mov esp,ebp
  31. 004012E4 pop ebp
  32. 004012E5 ret
    我们发现,manager的构造里面添加了employee的缺省构造函数,那么析构函数呢?


 
 
  1. 69: ~manager() { printf( "~maneger()!\n");}
  2. 00401350 push ebp
  3. 00401351 mov ebp,esp
  4. 00401353 sub esp, 44h
  5. 00401356 push ebx
  6. 00401357 push esi
  7. 00401358 push edi
  8. 00401359 push ecx
  9. 0040135A lea edi,[ebp -44h]
  10. 0040135D mov ecx, 11h
  11. 00401362 mov eax, 0CCCCCCCCh
  12. 00401367 rep stos dword ptr [edi]
  13. 00401369 pop ecx
  14. 0040136A mov dword ptr [ebp -4],ecx
  15. 0040136D push offset string "~maneger()!\n" ( 00431040)
  16. 00401372 call printf ( 004086e0)
  17. 00401377 add esp, 4
  18. 0040137A mov ecx,dword ptr [ebp -4]
  19. 0040137D call @ILT+ 5(employee::~employee) ( 0040100a)
  20. 00401382 pop edi
  21. 00401383 pop esi
  22. 00401384 pop ebx
  23. 00401385 add esp, 44h
  24. 00401388 cmp ebp,esp
  25. 0040138A call __chkesp ( 00408760)
  26. 0040138F mov esp,ebp
  27. 00401391 pop ebp
  28. 00401392 ret
    我们发现,manager构造的时候employee率先构造,然后打印manager;析构的时候,恰恰相反,manager首先析构自己,然后在再调用employee的析构函数,上面的汇编代码证明了一切。



【预告:下面主要讨论类的虚函数】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值