思考virtual析构

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

Author:zfive5(zhaozidong)

Email:zfive5@yahoo.com.cn

最近同住的朋友忙着找工作,他C++的问题看了一堆,我也受其影响复习了一些C++知识, virtual析构听他说“点播率还挺高的”,所以拿来仔细研究,求个深解!

首先,定义3个类,注意了析构函数的virtual 说明

class ZF5_1

{

public:

ZF5_1()

{

}

virtual ~ZF5_1()

{

printf("Hello ZF5_1\r\n");

}

};

class ZF5_2:public ZF5_1

{

public:

ZF5_2()

{

};

virtual ~ZF5_2()

{

printf("Hello ZF5_2\r\n");

};

};

class ZF5_3:public ZF5_2

{

public:

ZF5_3()

{

};

virtual ~ZF5_3()

{

printf("Hello ZF5_3\r\n");

};

};

然后执行代码:

ZF5_1 *p5=new ZF5_3;

delete p5;

1.如果都有virtual

输出:

Hello ZF5_3

Hello ZF5_2

Hello ZF5_1

2.如果都去掉virtual

输出:

Hello ZF5_1

3.如果只去掉ZF5_2的virtual

输出:

Hello ZF5_3

Hello ZF5_2

Hello ZF5_1

第一种情况

虽然delete是基类指针,但由于有virtual析构声明,所以delete调用的派生类的析构(派生类用自己的析构函数指针重写虚函数表),然后派生类析构完成后再调用直接基类析构(C++就是这样规定的,编译器隐含这个过程,通过看汇编代码,一切机理ok),这样一级级的调用,就出现了第一种输出!

第二种情况

由于没有virtual修饰,所以delete调用是默认的ZF5_1析构,出现第二种输出就理所当然了。

第三种情况

由于ZF5_1用virtual修饰,所以以后所有它的派生类用自己的析构函数指针重写虚函数表里的对应的位置,以至出现与第一种情况相同的结果!

有一种情况没有表达,就是如果定义如下:

virtual ZF5_1

ZF5_2

ZF5_3

ZF5_4

ZF5_2 *p1=new Z5_4;

delete p1;

输出:

Hello ZF5_4

Hello ZF5_3

Hello ZF5_2

Hello ZF5_1

这种情况在VC6下,只要有基类virtual声名,以后的派生类都自动加上virtual,不知道gcc和cb是怎样处理这种情况的!有机会验证一下,对了很有可能是C++标准规定,看来还得先去翻翻C++ Primer了。

ZF5_3析构完成后默认调用ZF5_2析构汇编代码:(VC6环境下)

52: ~ZF5_3()

53: {

004013E0 push ebp

004013E1 mov ebp,esp

004013E3 sub esp,44h

004013E6 push ebx

004013E7 push esi

004013E8 push edi

004013E9 push ecx

004013EA lea edi,[ebp-44h]

004013ED mov ecx,11h

004013F2 mov eax,0CCCCCCCCh

004013F7 rep stos dword ptr [edi]

004013F9 pop ecx

004013FA mov dword ptr [ebp-4],ecx

004013FD mov eax,dword ptr [ebp-4]

00401400 mov dword ptr [eax],offset ZF5_3::`vftable' (00423044)

54: printf("Hello ZF5_3\r\n");

00401406 push offset string "Hello ZF5_3\r\n" (00424050)

0040140B call printf (00401e40)

00401410 add esp,4

55: };

00401413 mov ecx,dword ptr [ebp-4]

00401416 call @ILT+145(ZF5_2::~ZF5_2) (00401096)

0040141B pop edi

0040141C pop esi

0040141D pop ebx

0040141E add esp,44h

00401421 cmp ebp,esp

00401423 call __chkesp (00401e00)

00401428 mov esp,ebp

0040142A pop ebp

0040142B ret

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航