C++构造函数和析构函数机制.docx

上传人:b****0 文档编号:12581932 上传时间:2023-04-20 格式:DOCX 页数:29 大小:50.12KB
下载 相关 举报
C++构造函数和析构函数机制.docx_第1页
第1页 / 共29页
C++构造函数和析构函数机制.docx_第2页
第2页 / 共29页
C++构造函数和析构函数机制.docx_第3页
第3页 / 共29页
C++构造函数和析构函数机制.docx_第4页
第4页 / 共29页
C++构造函数和析构函数机制.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

C++构造函数和析构函数机制.docx

《C++构造函数和析构函数机制.docx》由会员分享,可在线阅读,更多相关《C++构造函数和析构函数机制.docx(29页珍藏版)》请在冰豆网上搜索。

C++构造函数和析构函数机制.docx

C++构造函数和析构函数机制

在开始之前,先做好如下准备工作:

classMammal

{

public:

Mammal()

{

cout<<"\nmammalconstructor\n"<

}

virtual~Mammal()

{

cout<<"\nmammaldesturctor\n"<

}

public:

intGetAge(void)const

{

returnitsAge;

}

voidSetAge(intnewAge)

{

itsAge=newAge;

}

intGetWeight(void)const

{

returnitsWeight;

}

voidSetWeight(intnewWeight)

{

itsWeight=newWeight;

}

public:

voidSpeek(void)const

{

cout<<"\nMammalSond!

\n"<

}

voidSpeek(intspkTimes)const

{

cout<<"\nMammalSond:

"<

}

virtualvoidSleep(void)const

{

cout<<"\nMammalSleep\n"<

}

protected:

intitsAge;

intitsWeight;

};

classHorse:

publicMammal

{

public:

Horse(){cout<<"\nHorseconstructor\n"<

virtual~Horse(){cout<<"\nHorsedestructor\n"<

public:

virtualvoidSleep(void)const

{

cout<<"\nHorseSleep\n"<

}

};

intmain(void)

{

Mammal*mammalPtr=newHorse;

deletemammalPtr;

return0;

}

1、构造函数:

 

Mammal*mammalPtr=newHorse;的汇编代码如下:

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

既然是研究构造函数机制,那么先忽略掉无关内容,

0040123Acall@ILT+170(Horse:

:

Horse)(004010af)

是这一段汇编代码在本问题中的主要内容。

即,在定义一个对象时会自动调用类的构造函数。

下面再来具体看Horse的构造函数是什么样的:

114:

Horse(){cout<<"\nHorseconstructor\n"<

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"\nHorseconstructor\n"(0043001c)

00401554pushoffsetstd:

:

cout(00434eb0)

00401559call@ILT+220(std:

:

operator<<)(004010e1)

0040155Eaddesp,8

00401561movecx,eax

00401563call@ILT+160(std:

:

basic_ostream

:

char_traits>:

:

operator<<)(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

去除无关内容。

仅保留函数调用:

114:

Horse(){cout<<"\nHorseconstructor\n"<

00401535call@ILT+45(Mammal:

:

Mammal)(00401032)

00401559call@ILT+220(std:

:

operator<<)(004010e1)

00401563call@ILT+160(std:

:

basic_ostream

:

char_traits>:

:

operator<<)(004010a5)

00401584call__chkesp(00409ba0)

0040158Cret

第一个call调用了基类的构造函数;第二个call调用重载运算符;第三个call调用输出语句输出;第四个call调用栈检查函数。

由此可见,Horse(){cout<<"\nHorseconstructor\n"<

2、析构函数:

15:

deletemammalPtr;

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

去除无关内容。

仅保留函数调用:

15:

deletemammalPtr;

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]

00401280call__chkesp(00409ba0)

由于析构函数是个虚函数,所以先在虚函数表中查找出析构函数的地址,然后再对析构函数进行调用。

下面再来具体看Horse的析构函数是什么样的:

115:

virtual~Horse(){cout<<"\nHorsedestructor\n"<

004027C0pushebp

004027C1movebp,esp

004027C3push0FFh

004027C5pushoffset__ehhandler$?

?

1Horse@@UAE@XZ(0041d9e9)

004027CAmoveax,fs:

[00000000]

004027D0pusheax

004027D1movdwordptrfs:

[0],esp

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:

:

`vftable'(00430034)

004027FBmovdwordptr[ebp-4],0

00402802pushoffset@ILT+70(std:

:

endl)(0040104b)

00402807pushoffsetstring"\nHorsedestructor\n"(004300a4)

0040280Cpushoffsetstd:

:

cout(00434eb0)

00402811call@ILT+220(std:

:

operator<<)(004010e1)

00402816addesp,8

00402819movecx,eax

0040281Bcall@ILT+160(std:

:

basic_ostream

:

char_traits>:

:

operator<<)(004010a5)

00402820movdwordptr[ebp-4],0FFFFFFFFh

00402827movecx,dwordptr[ebp-10h]

0040282Acall@ILT+120(Mammal:

:

~Mammal)(0040107d)

0040282Fmovecx,dwordptr[ebp-0Ch]

00402832movdwordptrfs:

[0],ecx

00402839popedi

0040283Apopesi

0040283Bpopebx

0040283Caddesp,50h

0040283Fcmpebp,esp

00402841call__chkesp(00409ba0)

00402846movesp,ebp

00402848popebp

00402849ret

去除无关内容。

仅保留函数调用:

115:

virtual~Horse(){cout<<"\nHorsedestructor\n"<

00402811call@ILT+220(std:

:

operator<<)(004010e1)

0040281Bcall@ILT+160(std:

:

basic_ostream

:

char_traits>:

:

operator<<)(004010a5)

0040282Acall@ILT+120(Mammal:

:

~Mammal)(0040107d)

00402841call__chkesp(00409ba0)

00402849ret

第一个call调用重载运算符;第二个call调用输出函数;第三个call调用基类析构函数;第四个call调用栈检测函数,检测占空间有没有被破坏。

由此可见,子类析构函数会先运行用户所写的代码,运行完了后编译器在后面插入了调用基类析构函数的指令。

由此可以调用所有相关的析构函数。

这是构造函数为虚函数所发生的情况。

如果析构函数不是虚函数呢?

1、基类析构函数为虚函数,子类构造函数为非虚函数

classMammal

{

public:

Mammal()

{

cout<<"\nmammalconstructor\n"<

}

virtual~Mammal()

{

cout<<"\nmammaldesturctor\n"<

}

public:

intGetAge(void)const

{

returnitsAge;

}

voidSetAge(intnewAge)

{

itsAge=newAge;

}

intGetWeight(void)const

{

returnitsWeight;

}

voidSetWeight(intnewWeight)

{

itsWeight=newWeight;

}

public:

voidSpeek(void)const

{

cout<<"\nMammalSond!

\n"<

}

voidSpeek(intspkTimes)const

{

cout<<"\nMammalSond:

"<

}

virtualvoidSleep(void)const

{

cout<<"\nMammalSleep\n"<

}

 

protected:

intitsAge;

intitsWeight;

};

classHorse:

publicMammal

{

public:

Horse(){cout<<"\nHorseconstructor\n"<

~Horse(){cout<<"\nHorsedestructor\n"<

public:

virtualvoidSleep(void)const

{

cout<<"\nHorseSleep\n"<

}

};

intmain(void)

{

Mammal*mammalPtr=newHorse;

deletemammalPtr;

return0;

}

运行结果:

汇编代码:

15:

deletemammalPtr;

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

去除无关内容。

仅保留函数调用:

15:

deletemammalPtr;

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]

00401280call__chkesp(00409ba0)

结合输出结果由此课件,子类的析构函数虽然没有在前面加virtual但是由于基类的析构函数是virtual的,所以编译器自动将子类的构造函数也设置为virtual的,因此可以正常调用子类析构函数和基类析构函数。

2、基类析构函数为非虚函数,子类构造函数为虚函数

classMammal

{

public:

Mammal()

{

cout<<"\nmammalconstructor\n"<

}

~Mammal()

{

cout<<"\nmammaldesturctor\n"<

}

public:

intGetAge(void)const

{

returnitsAge;

}

voidSetAge(intnewAge)

{

itsAge=newAge;

}

intGetWeight(void)const

{

returnitsWeight;

}

voidSetWeight(intnewWeight)

{

itsWeight=newWeight;

}

public:

voidSpeek(void)const

{

cout<<"\nMammalSond!

\n"<

}

voidSpeek(intspkTimes)const

{

cout<<"\nMammalSond:

"<

}

virtualvoidSleep(void)const

{

cout<<"\nMammalSleep\n"<

}

 

protected:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1