1、C+构造函数和析构函数机制在开始之前,先做好如下准备工作:class Mammal public: Mammal() cout nmammal constructorn endl; virtual Mammal() cout nmammal desturctorn endl; public: int GetAge(void) const return itsAge; void SetAge(int newAge) itsAge = newAge; int GetWeight(void) const return itsWeight; void SetWeight(int newWeight)
2、itsWeight = newWeight; public: void Speek(void) const cout nMammal Sond!n endl ; void Speek(int spkTimes) const cout nMammal Sond:spkTimestimesn endl ; virtual void Sleep(void) const cout nMammal Sleepn endl ; protected: int itsAge; int itsWeight;class Horse : public Mammal public: Horse()cout nHors
3、e constructorn endl; virtual Horse()cout nHorse destructorn endl; public: virtual void Sleep(void) const cout nHorse Sleepn endl; ;int main(void) Mammal* mammalPtr = new Horse; delete mammalPtr; return 0;1、构造函数: Mammal* mammalPtr = new Horse;的汇编代码如下:0040121D push 0Ch0040121F call operator new (00409
4、6b0)00401224 add esp,400401227 mov dword ptr ebp-18h,eax0040122A mov dword ptr ebp-4,000401231 cmp dword ptr ebp-18h,000401235 je main+54h (00401244)00401237 mov ecx,dword ptr ebp-18h0040123A call ILT+170(Horse:Horse) (004010af)0040123F mov dword ptr ebp-24h,eax00401242 jmp main+5Bh (0040124b)004012
5、44 mov dword ptr ebp-24h,00040124B mov eax,dword ptr ebp-24h0040124E mov dword ptr ebp-14h,eax00401251 mov dword ptr ebp-4,0FFFFFFFFh00401258 mov ecx,dword ptr ebp-14h0040125B mov dword ptr ebp-10h,ecx既然是研究构造函数机制,那么先忽略掉无关内容,0040123A call ILT+170(Horse:Horse) (004010af)是这一段汇编代码在本问题中的主要内容。即,在定义一个对象时会自
6、动调用类的构造 函数。下面再来具体看Horse的构造函数是什么样的:114: Horse()cout nHorse constructorn endl;00401500 push ebp00401501 mov ebp,esp00401503 push 0FFh00401505 push offset _ehhandler$?0HorseQAEXZ (0041d989)0040150A mov eax,fs:0000000000401510 push eax00401511 mov dword ptr fs:0,esp00401518 sub esp,44h0040151B push ebx0
7、040151C push esi0040151D push edi0040151E push ecx0040151F lea edi,ebp-50h00401522 mov ecx,11h00401527 mov eax,0CCCCCCCCh0040152C rep stos dword ptr edi0040152E pop ecx0040152F mov dword ptr ebp-10h,ecx00401532 mov ecx,dword ptr ebp-10h00401535 call ILT+45(Mammal:Mammal) (00401032)0040153A mov dword
8、 ptr ebp-4,000401541 mov eax,dword ptr ebp-10h00401544 mov dword ptr eax,offset Horse:vftable (00430034)0040154A push offset ILT+70(std:endl) (0040104b)0040154F push offset string nHorse constructorn (0043001c)00401554 push offset std:cout (00434eb0)00401559 call ILT+220(std:operator) (004010e1)0040
9、155E add esp,800401561 mov ecx,eax00401563 call ILT+160(std:basic_ostreamchar,std:char_traits :operator) (004010a5)00401568 mov dword ptr ebp-4,0FFFFFFFFh0040156F mov eax,dword ptr ebp-10h00401572 mov ecx,dword ptr ebp-0Ch00401575 mov dword ptr fs:0,ecx0040157C pop edi0040157D pop esi0040157E pop eb
10、x0040157F add esp,50h00401582 cmp ebp,esp00401584 call _chkesp (00409ba0)00401589 mov esp,ebp0040158B pop ebp0040158C ret去除无关内容。仅保留函数调用:114: Horse()cout nHorse constructorn endl;00401535 call ILT+45(Mammal:Mammal) (00401032)00401559 call ILT+220(std:operator) (004010e1)00401563 call ILT+160(std:basi
11、c_ostreamchar,std:char_traits :operator) (004010a5)00401584 call _chkesp (00409ba0)0040158C ret第一个call调用了基类的构造函数;第二个call调用重载运算符;第三个call调用输出语句输出;第四个call调用栈检查函数。由此可见,Horse()cout nHorse constructorn endl;在运行时,编译器会在前面插入必要的语句来实现一些重要功能,比如说先调用基类构造函数,然后才运行用户写入的代码。2、析构函数:15: delete mammalPtr;0040125E mov edx
12、,dword ptr ebp-10h00401261 mov dword ptr ebp-20h,edx00401264 mov eax,dword ptr ebp-20h00401267 mov dword ptr ebp-1Ch,eax0040126A cmp dword ptr ebp-1Ch,00040126E je main+9Ah (0040128a)00401270 mov esi,esp00401272 push 100401274 mov ecx,dword ptr ebp-1Ch00401277 mov edx,dword ptr ecx00401279 mov ecx,d
13、word ptr ebp-1Ch0040127C call dword ptr edx0040127E cmp esi,esp00401280 call _chkesp (00409ba0)00401285 mov dword ptr ebp-28h,eax00401288 jmp main+0A1h (00401291)0040128A mov dword ptr ebp-28h,0去除无关内容。仅保留函数调用:15: delete mammalPtr;0040125E mov edx,dword ptr ebp-10h00401261 mov dword ptr ebp-20h,edx00
14、401264 mov eax,dword ptr ebp-20h00401267 mov dword ptr ebp-1Ch,eax0040126A cmp dword ptr ebp-1Ch,00040126E je main+9Ah (0040128a)00401270 mov esi,esp00401272 push 100401274 mov ecx,dword ptr ebp-1Ch00401277 mov edx,dword ptr ecx00401279 mov ecx,dword ptr ebp-1Ch0040127C call dword ptr edx00401280 ca
15、ll _chkesp (00409ba0)由于析构函数是个虚函数,所以先在虚函数表中查找出析构函数的地址,然后再对析构函数进行调用。下面再来具体看Horse的析构函数是什么样的:115: virtual Horse()cout nHorse destructorn endl;004027C0 push ebp004027C1 mov ebp,esp004027C3 push 0FFh004027C5 push offset _ehhandler$?1HorseUAEXZ (0041d9e9)004027CA mov eax,fs:00000000004027D0 push eax004027D
16、1 mov dword ptr fs:0,esp004027D8 sub esp,44h004027DB push ebx004027DC push esi004027DD push edi004027DE push ecx004027DF lea edi,ebp-50h004027E2 mov ecx,11h004027E7 mov eax,0CCCCCCCCh004027EC rep stos dword ptr edi004027EE pop ecx004027EF mov dword ptr ebp-10h,ecx004027F2 mov eax,dword ptr ebp-10h00
17、4027F5 mov dword ptr eax,offset Horse:vftable (00430034)004027FB mov dword ptr ebp-4,000402802 push offset ILT+70(std:endl) (0040104b)00402807 push offset string nHorse destructorn (004300a4)0040280C push offset std:cout (00434eb0)00402811 call ILT+220(std:operator) (004010e1)00402816 add esp,800402
18、819 mov ecx,eax0040281B call ILT+160(std:basic_ostreamchar,std:char_traits :operator) (004010a5)00402820 mov dword ptr ebp-4,0FFFFFFFFh00402827 mov ecx,dword ptr ebp-10h0040282A call ILT+120(Mammal:Mammal) (0040107d)0040282F mov ecx,dword ptr ebp-0Ch00402832 mov dword ptr fs:0,ecx00402839 pop edi004
19、0283A pop esi0040283B pop ebx0040283C add esp,50h0040283F cmp ebp,esp00402841 call _chkesp (00409ba0)00402846 mov esp,ebp00402848 pop ebp00402849 ret去除无关内容。仅保留函数调用:115: virtual Horse()cout nHorse destructorn endl; 00402811 call ILT+220(std:operator) (004010e1)0040281B call ILT+160(std:basic_ostreamc
20、har,std:char_traits :operator) (004010a5)0040282A call ILT+120(Mammal:Mammal) (0040107d)00402841 call _chkesp (00409ba0)00402849 ret第一个call调用重载运算符;第二个call调用输出函数;第三个call调用基类析构函数;第四个call调用栈检测函数,检测占空间有没有被破坏。由此可见,子类析构函数会先运行用户所写的代码,运行完了后编译器在后面插入了调用基类析构函数的指令。由此可以调用所有相关的析构函数。这是构造函数为虚函数所发生的情况。如果析构函数不是虚函数呢?1
21、、基类析构函数为虚函数,子类构造函数为非虚函数class Mammal public: Mammal() cout nmammal constructorn endl; virtual Mammal() cout nmammal desturctorn endl; public: int GetAge(void) const return itsAge; void SetAge(int newAge) itsAge = newAge; int GetWeight(void) const return itsWeight; void SetWeight(int newWeight) itsWei
22、ght = newWeight; public: void Speek(void) const cout nMammal Sond!n endl ; void Speek(int spkTimes) const cout nMammal Sond: spkTimes timesn endl ; virtual void Sleep(void) const cout nMammal Sleepn endl ; protected: int itsAge; int itsWeight;class Horse : public Mammal public: Horse()cout nHorse co
23、nstructorn endl; Horse()cout nHorse destructorn endl; public: virtual void Sleep(void) const cout nHorse Sleepn endl; ;int main(void) Mammal* mammalPtr = new Horse; delete mammalPtr; return 0;运行结果:汇编代码:15: delete mammalPtr;0040125E mov edx,dword ptr ebp-10h00401261 mov dword ptr ebp-20h,edx00401264
24、mov eax,dword ptr ebp-20h00401267 mov dword ptr ebp-1Ch,eax0040126A cmp dword ptr ebp-1Ch,00040126E je main+9Ah (0040128a)00401270 mov esi,esp00401272 push 100401274 mov ecx,dword ptr ebp-1Ch00401277 mov edx,dword ptr ecx00401279 mov ecx,dword ptr ebp-1Ch0040127C call dword ptr edx0040127E cmp esi,e
25、sp00401280 call _chkesp (00409ba0)00401285 mov dword ptr ebp-28h,eax00401288 jmp main+0A1h (00401291)0040128A mov dword ptr ebp-28h,0去除无关内容。仅保留函数调用:15: delete mammalPtr;0040125E mov edx,dword ptr ebp-10h00401261 mov dword ptr ebp-20h,edx00401264 mov eax,dword ptr ebp-20h00401267 mov dword ptr ebp-1C
26、h,eax0040126A cmp dword ptr ebp-1Ch,00040126E je main+9Ah (0040128a)00401270 mov esi,esp00401272 push 100401274 mov ecx,dword ptr ebp-1Ch00401277 mov edx,dword ptr ecx00401279 mov ecx,dword ptr ebp-1Ch0040127C call dword ptr edx00401280 call _chkesp (00409ba0)结合输出结果由此课件,子类的析构函数虽然没有在前面加virtual但是由于基类的
27、析构函数是virtual的,所以编译器自动将子类的构造函数也设置为virtual的,因此可以正常调用子类析构函数和基类析构函数。2、基类析构函数为非虚函数,子类构造函数为虚函数class Mammal public: Mammal() cout nmammal constructorn endl; Mammal() cout nmammal desturctorn endl; public: int GetAge(void) const return itsAge; void SetAge(int newAge) itsAge = newAge; int GetWeight(void) const return itsWeight; void SetWeight(int newWeight) itsWeight = newWeight; public: void Speek(void) const cout nMammal Sond!n endl ; void Speek(int spkTimes) const cout nMammal Sond: spkTimes timesn endl ; virtual void Sleep(void) const cout nMammal Sleepn endl ; protected:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1