版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
继承是类的一个基本属性,可是在类的继承过程中,函数是怎么初始化?怎么析构的呢?我们不妨看看下面这样的一段代码?
-
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,那么在内存构建和析构的时候函数又是怎么安排的呢?
-
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
-
0040128
0 call __chkesp (
0040876
0)
-
00401285 mov esp,ebp
-
00401287
pop ebp
我们发现manager的构造和析构其实也简单。构造函数其实就是在变量出现的时候进行构造。那什么时候析构呢?也就在函数快结束的时候进行析构。下面我们可以进一步讨论在manager的构造和析构究竟是怎么做的?
-
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的缺省构造函数,那么析构函数呢?
-
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的析构函数,上面的汇编代码证明了一切。
【预告:下面主要讨论类的虚函数】