zoukankan      html  css  js  c++  java
  • 用汇编的眼光看C++(之类继承) 四

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


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

    1. class employee  
    2. {  
    3. public:  
    4.     employee() { printf("employee()!\n");}  
    5.     ~employee() { printf("~employee()!\n");}  
    6. };  
    7.   
    8. class manager : public employee  
    9. {  
    10. public:  
    11.     manager() { printf("manager()!\n");}  
    12.     ~manager() {  printf("~maneger()!\n");}  
    13. };  
        看到上面的代码,相信大家也明白了,我们定义了这样一个类。基类是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. 00401280   call        __chkesp (00408760)  
    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的析构函数,上面的汇编代码证明了一切。
  • 相关阅读:
    (转)sqlite3生成lib遇到的问题
    C++中的static
    static int和static final int的区别
    用static关键字修饰类
    Shell脚本的编写
    linux定时任务的设置 crontab 配置指南
    s3cmd的安装与配置
    s3cmd的安装与使用
    -Dmaven.multiModuleProjectDirectory system propery is not set.
    maven 环境搭建 Myeclipse配置
  • 原文地址:https://www.cnblogs.com/sier/p/5676488.html
Copyright © 2011-2022 走看看