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

来源:岁月联盟 编辑:exp 时间:2011-10-05

 

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

 

 

 

 

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

 

 

copy to clipboardprint?class employee 

public: 

    employee() { printf("employee()!/n");} 

    ~employee() { printf("~employee()!/n");} 

}; 

 

class manager : public employee 

public: 

    manager() { printf("manager()!/n");} 

    ~manager() {  printf("~maneger()!/n");} 

}; 

class employee

{

public:

       employee() { printf("employee()!/n");}

       ~employee() { printf("~employee()!/n");}

};

 

class manager : public employee

{

public:

       manager() { printf("manager()!/n");}

       ~manager() {  printf("~maneger()!/n");}

};    看到上面的代码,相信大家也明白了,我们定义了这样一个类。基类是empoyee,继承类是manager。我们看到manager是一种特殊的employee,那么在内存构建和析构的时候函数又是怎么安排的呢?

 

 

copy to clipboardprint?74:       manager m; 

00401268   lea         ecx,[ebp-4] 

0040126B   call        @ILT+60(manager::manager) (00401041) 

75:   } 

00401270   lea         ecx,[ebp-4] 

00401273   call        @ILT+0(manager::~manager) (00401005) 

00401278   pop         edi 

00401279   pop         esi 

0040127A   pop         ebx 

0040127B   add         esp,44h 

0040127E   cmp         ebp,esp 

00401280   call        __chkesp (00408760) 

00401285   mov         esp,ebp 

00401287   pop         ebp 

74:       manager m;

00401268   lea         ecx,[ebp-4]

0040126B   call        @ILT+60(manager::manager) (00401041)

75:   }

00401270   lea         ecx,[ebp-4]

00401273   call        @ILT+0(manager::~manager) (00401005)

00401278   pop         edi

00401279   pop         esi

0040127A   pop         ebx

0040127B   add         esp,44h

0040127E   cmp         ebp,esp

00401280   call        __chkesp (00408760)

00401285   mov         esp,ebp

00401287   pop         ebp

    我们发现manager的构造和析构其实也简单。构造函数其实就是在变量出现的时候进行构造。那什么时候析构呢?也就在函数快结束的时候进行析构。下面我们可以进一步讨论在manager的构造和析构究竟是怎么做的?

 

 

copy to clipboardprint?65:   class manager : public employee 

66:   { 

67:   public: 

68:       manager() { printf("manager()!/n");} 

004012A0   push        ebp 

004012A1   mov         ebp,esp 

004012A3   sub         esp,44h 

004012A6   push        ebx 

004012A7   push        esi 

004012A8   push        edi 

004012A9   push        ecx 

004012AA   lea         edi,[ebp-44h] 

004012AD   mov         ecx,11h 

004012B2   mov         eax,0CCCCCCCCh 

004012B7   rep stos    dword ptr [edi] 

004012B9   pop         ecx 

004012BA   mov         dword ptr [ebp-4],ecx 

004012BD   mov         ecx,dword ptr [ebp-4] 

004012C0   call        @ILT+40(employee::employee) (0040102d) 

004012C5   push        offset string "manager()!/n" (00431020) 

004012CA   call        printf (004086e0) 

004012CF   add         esp,4 

004012D2   mov         eax,dword ptr [ebp-4] 

004012D5   pop         edi 

004012D6   pop         esi 

004012D7   pop         ebx 

004012D8   add         esp,44h 

004012DB   cmp         ebp,esp 

004012DD   call        __chkesp (00408760) 

004012E2   mov         esp,ebp 

004012E4   pop         ebp 

004012E5   ret 

65:   class manager : public employee

66:   {

67:   public:

68:       manager() { printf("manager()!/n");}

004012A0   push        ebp

004012A1   mov         ebp,esp

004012A3   sub         esp,44h

004012A6   push        ebx

004012A7   push        esi

004012A8   push        edi

004012A9   push        ecx

004012AA   lea         edi,[ebp-44h]

004012AD   mov         ecx,11h

004012B2   mov         eax,0CCCCCCCCh

004012B7   rep stos    dword ptr [edi]

004012B9   pop         ecx

004012BA   mov         dword ptr [ebp-4],ecx

004012BD   mov         ecx,dword ptr [ebp-4]

004012C0   call        @ILT+40(employee::employee) (0040102d)

004012C5   push        offset string "manager()!/n" (00431020)

004012CA   call        printf (004086e0)

004012CF   add         esp,4

004012D2   mov         eax,dword ptr [ebp-4]

004012D5   pop         edi

004012D6   pop         esi

004012D7   pop         ebx

004012D8   add         esp,44h

004012DB   cmp         ebp,esp

004012DD   call        __chkesp (00408760)

004012E2   mov         esp,ebp

004012E4   pop         ebp

004012E5   ret

    我们发现,manager的构造里面添加了employee的缺省构造函数,那么析构函数呢?

 

 

copy to clipboardprint?69:       ~manager() {  printf("~maneger()!/n");} 

00401350   push        ebp 

00401351   mov         ebp,esp 

00401353   sub         esp,44h 

00401356   push        ebx 

00401357   push        esi 

00401358   push        edi 

00401359   push        ecx 

0040135A   lea         edi,[ebp-44h] 

0040135D   mov         ecx,11h 

00401362   mov         eax,0CCCCCCCCh 

00401367   rep stos    dword ptr [edi] 

00401369   pop         ecx 

0040136A   mov         dword ptr [ebp-4],ecx 

0040136D   push        offset string "~maneger()!/n" (00431040) 

00401372   call        printf (004086e0) 

00401377   add         esp,4 

0040137A   mov         ecx,dword ptr [ebp-4] 

0040137D   call        @ILT+5(employee::~employee) (0040100a) 

00401382   pop         edi 

00401383   pop         esi 

00401384   pop         ebx 

00401385   add         esp,44h 

00401388   cmp         ebp,esp 

0040138A   call        __chkesp (00408760) 

0040138F   mov         esp,ebp 

00401391   pop         ebp 

00401392   ret 

69:       ~manager() {  printf("~maneger()!/n");}

00401350   push        ebp

00401351   mov         ebp,esp

00401353   sub         esp,44h

00401356   push        ebx

00401357   push        esi

00401358   push        edi

00401359   push        ecx

0040135A   lea         edi,[ebp-44h]

0040135D   mov         ecx,11h

00401362   mov         eax,0CCCCCCCCh

00401367   rep stos    dword ptr [edi]

00401369   pop         ecx

0040136A   mov         dword ptr [ebp-4],ecx

0040136D   push        offset string "~maneger()!/n" (00431040)

00401372   call        printf (004086e0)

00401377   add         esp,4

0040137A   mov         ecx,dword ptr [ebp-4]

0040137D   call        @ILT+5(employee::~employee) (0040100a)

00401382   pop         edi

00401383   pop         esi

00401384   pop         ebx

00401385   add         esp,44h

00401388   cmp         ebp,esp

0040138A   call        __chkesp (00408760)

0040138F   mov         esp,ebp

00401391   pop         ebp

00401392   ret

    我们发现,manager构造的时候employee率先构造,然后打印manager;析构的时候,恰恰相反,manager首先析构自己,然后在再调用employee的析构函数,上面的汇编代码证明了一切。