您的位置:首页 > 编程语言 > C语言/C++

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

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

[cpp] view
plaincopy

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,那么在内存构建和析构的时候函数又是怎么安排的呢?

[cpp] view
plaincopy

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的构造和析构究竟是怎么做的?

[cpp] view
plaincopy

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的缺省构造函数,那么析构函数呢?

[cpp] view
plaincopy

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的析构函数,上面的汇编代码证明了一切。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: