思考virtual析构

C++中virtual析构函数的深入研究

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_2virtual

输出:

Hello ZF5_3

Hello ZF5_2

Hello ZF5_1

第一种情况

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

第二种情况

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

第三种情况

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

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

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,不知道gcccb是怎样处理这种情况的!有机会验证一下,对了很有可能是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值