C++构造函数和析构函数机制Word文件下载.docx
《C++构造函数和析构函数机制Word文件下载.docx》由会员分享,可在线阅读,更多相关《C++构造函数和析构函数机制Word文件下载.docx(29页珍藏版)》请在冰点文库上搜索。
![C++构造函数和析构函数机制Word文件下载.docx](https://file1.bingdoc.com/fileroot1/2023-5/1/c820ea4e-d5e4-4b19-bc38-d02de6aecbf4/c820ea4e-d5e4-4b19-bc38-d02de6aecbf41.gif)
itsWeight=newWeight;
voidSpeek(void)const
\nMammalSond!
\n"
endl;
voidSpeek(intspkTimes)const
\nMammalSond:
"
spkTimes<
times\n"
virtualvoidSleep(void)const
\nMammalSleep\n"
protected:
intitsAge;
intitsWeight;
};
classHorse:
publicMammal
Horse(){cout<
\nHorseconstructor\n"
}
virtual~Horse(){cout<
\nHorsedestructor\n"
\nHorseSleep\n"
intmain(void)
Mammal*mammalPtr=newHorse;
deletemammalPtr;
return0;
1、构造函数:
的汇编代码如下:
0040121Dpush0Ch
0040121Fcalloperatornew(004096b0)
00401224addesp,4
00401227movdwordptr[ebp-18h],eax
0040122Amovdwordptr[ebp-4],0
00401231cmpdwordptr[ebp-18h],0
00401235jemain+54h(00401244)
00401237movecx,dwordptr[ebp-18h]
0040123Acall@ILT+170(Horse:
:
Horse)(004010af)
0040123Fmovdwordptr[ebp-24h],eax
00401242jmpmain+5Bh(0040124b)
00401244movdwordptr[ebp-24h],0
0040124Bmoveax,dwordptr[ebp-24h]
0040124Emovdwordptr[ebp-14h],eax
00401251movdwordptr[ebp-4],0FFFFFFFFh
00401258movecx,dwordptr[ebp-14h]
0040125Bmovdwordptr[ebp-10h],ecx
既然是研究构造函数机制,那么先忽略掉无关内容,
是这一段汇编代码在本问题中的主要内容。
即,在定义一个对象时会自动调用类的构造函数。
下面再来具体看Horse的构造函数是什么样的:
114:
Horse(){cout<
00401500pushebp
00401501movebp,esp
00401503push0FFh
00401505pushoffset__ehhandler$?
?
0Horse@@QAE@XZ(0041d989)
0040150Amoveax,fs:
[00000000]
00401510pusheax
00401511movdwordptrfs:
[0],esp
00401518subesp,44h
0040151Bpushebx
0040151Cpushesi
0040151Dpushedi
0040151Epushecx
0040151Fleaedi,[ebp-50h]
00401522movecx,11h
00401527moveax,0CCCCCCCCh
0040152Crepstosdwordptr[edi]
0040152Epopecx
0040152Fmovdwordptr[ebp-10h],ecx
00401532movecx,dwordptr[ebp-10h]
00401535call@ILT+45(Mammal:
Mammal)(00401032)
0040153Amovdwordptr[ebp-4],0
00401541moveax,dwordptr[ebp-10h]
00401544movdwordptr[eax],offsetHorse:
`vftable'
(00430034)
0040154Apushoffset@ILT+70(std:
endl)(0040104b)
0040154Fpushoffsetstring"
(0043001c)
00401554pushoffsetstd:
cout(00434eb0)
00401559call@ILT+220(std:
operator<
)(004010e1)
0040155Eaddesp,8
00401561movecx,eax
00401563call@ILT+160(std:
basic_ostream<
char,std:
char_traits<
char>
>
)(004010a5)
00401568movdwordptr[ebp-4],0FFFFFFFFh
0040156Fmoveax,dwordptr[ebp-10h]
00401572movecx,dwordptr[ebp-0Ch]
00401575movdwordptrfs:
[0],ecx
0040157Cpopedi
0040157Dpopesi
0040157Epopebx
0040157Faddesp,50h
00401582cmpebp,esp
00401584call__chkesp(00409ba0)
00401589movesp,ebp
0040158Bpopebp
0040158Cret
去除无关内容。
仅保留函数调用:
第一个call调用了基类的构造函数;
第二个call调用重载运算符;
第三个call调用输出语句输出;
第四个call调用栈检查函数。
由此可见,Horse(){cout<
}在运行时,编译器会在前面插入必要的语句来实现一些重要功能,比如说先调用基类构造函数,然后才运行用户写入的代码。
2、析构函数:
15:
0040125Emovedx,dwordptr[ebp-10h]
00401261movdwordptr[ebp-20h],edx
00401264moveax,dwordptr[ebp-20h]
00401267movdwordptr[ebp-1Ch],eax
0040126Acmpdwordptr[ebp-1Ch],0
0040126Ejemain+9Ah(0040128a)
00401270movesi,esp
00401272push1
00401274movecx,dwordptr[ebp-1Ch]
00401277movedx,dwordptr[ecx]
00401279movecx,dwordptr[ebp-1Ch]
0040127Ccalldwordptr[edx]
0040127Ecmpesi,esp
00401280call__chkesp(00409ba0)
00401285movdwordptr[ebp-28h],eax
00401288jmpmain+0A1h(00401291)
0040128Amovdwordptr[ebp-28h],0
由于析构函数是个虚函数,所以先在虚函数表中查找出析构函数的地址,然后再对析构函数进行调用。
下面再来具体看Horse的析构函数是什么样的:
115:
virtual~Horse(){cout<
004027C0pushebp
004027C1movebp,esp
004027C3push0FFh
004027C5pushoffset__ehhandler$?
1Horse@@UAE@XZ(0041d9e9)
004027CAmoveax,fs:
004027D0pusheax
004027D1movdwordptrfs:
004027D8subesp,44h
004027DBpushebx
004027DCpushesi
004027DDpushedi
004027DEpushecx
004027DFleaedi,[ebp-50h]
004027E2movecx,11h
004027E7moveax,0CCCCCCCCh
004027ECrepstosdwordptr[edi]
004027EEpopecx
004027EFmovdwordptr[ebp-10h],ecx
004027F2moveax,dwordptr[ebp-10h]
004027F5movdwordptr[eax],offsetHorse:
004027FBmovdwordptr[ebp-4],0
00402802pushoffset@ILT+70(std:
00402807pushoffsetstring"
(004300a4)
0040280Cpushoffsetstd:
00402811call@ILT+220(std:
00402816addesp,8
00402819movecx,eax
0040281Bcall@ILT+160(std:
00402820movdwordptr[ebp-4],0FFFFFFFFh
00402827movecx,dwordptr[ebp-10h]
0040282Acall@ILT+120(Mammal:
~Mammal)(0040107d)
0040282Fmovecx,dwordptr[ebp-0Ch]
00402832movdwordptrfs:
00402839popedi
0040283Apopesi
0040283Bpopebx
0040283Caddesp,50h
0040283Fcmpebp,esp
00402841call__chkesp(00409ba0)
00402846movesp,ebp
00402848popebp
00402849ret
}
第一个call调用重载运算符;
第二个call调用输出函数;
第三个call调用基类析构函数;
第四个call调用栈检测函数,检测占空间有没有被破坏。
由此可见,子类析构函数会先运行用户所写的代码,运行完了后编译器在后面插入了调用基类析构函数的指令。
由此可以调用所有相关的析构函数。
这是构造函数为虚函数所发生的情况。
如果析构函数不是虚函数呢?
1、基类析构函数为虚函数,子类构造函数为非虚函数
spkTimes<
~Horse(){cout<
运行结果:
汇编代码:
结合输出结果由此课件,子类的析构函数虽然没有在前面加virtual但是由于基类的析构函数是virtual的,所以编译器自动将子类的构造函数也设置为virtual的,因此可以正常调用子类析构函数和基类析构函数。
2、基类析构函数为非虚函数,子类构造函数为虚函数
~Mammal()