C++ 虚析构函数
来源:互联网 发布:淘宝发布宝贝app 编辑:程序博客网 时间:2024/04/29 16:16
C++类里面,我们经常可以看到析构函数是虚函数,这个虚函数有什么作用吗?我们可以通过一个很简单的例子来看看虚析构函数的作用。
class CBase{public:virtual ~CBase(){printf("CBase::~CBase()\n");}};class CChild: public CBase{public:virtual ~CChild(){printf("CChild::~CChild()\n");}};int _tmain(int argc, _TCHAR* argv[]){CChild* p = new CChild();delete p;CBase* p2 = new CChild();delete p2;return 0;}
一个基类,一个子类,相当的简单。先看下面2行代码:
CChild* p = new CChild();delete p;
delete p的时候调用基类还是子类的析构函数呢?其实这个问题很简单,p是CChild指针(子类),那么自然调用子类的析构函数了。基类析构函数会被调用吗?答案是肯定的,其实这个是C++的特性,子类的析构函数会自动调用基类的析构函数。子类析构是这样的过程:
1. 析构子类扩展部分(也就是运行子类析构函数代码);
2. 在子类析构函数返回之前调用基类析构函数来释放基类部分。
有图有真相:
从callstack里面 可以看的很清楚,在delete p的时候,先进入CChild析构函数~CChild(),然后~CChild()又调用了基类析构函数~CBase()。
这个过程跟析构函数是否是虚函数无关。也就是说:
无论析构函数是否是虚函数,子类的析构函数一定会调用基类的析构函数。顺序是先析构子类部分,再析构基类部分。
(对于构造函数,我们可以在子类的构造函数里面选择调用基类的某一个构造函数,如果不在子类里面显式地调用基类构造函数,那么系统自动会调用基类的默认构造函数。顺序刚好和析构相反,先构造基类部分,再构造子类部分)
我们再来看看这几行代码:
CBase* p2 = new CChild();delete p2;
delete p2的时候调用基类还是子类的析构函数呢?先来看看虚析构函数的情况:
从上面的图中,可以清楚的看到调用的是子类的析构函数。根据我们前面得出来的结论:子类析构函数会自动调用基类析构函数,那么对于这种情况(虚析构函数)就是:
子类和基类的析构函数都会被调用。(其中基类析构函数是被子类析构函数自动调用的)
再来看看非虚析构函数的情况,先看图:
我们会发现子类析构函数~CChild()并没有出现在call stack中,我们只看到了基类析构函数~CBase(),也就是说子类析构函数并没有被调用。
至此我们可以得出结论,对于delete一个指向子类的基类指针:
1. 对于虚析构函数,那么就是基类和子类的析构函数都会被调用,先析构子类部分,再析构基类部分。(基类析构函数是被子类析构函数自动调用的)
2. 对于非虚析构函数,子类析构函数不会被调用,只有基类析构函数才会被调用。
为什么虚析构函数的情况下,子类析构函数会被调用呢?这个地方就涉及到虚函数表的问题。当一个C++类里面有一个或者多个虚函数的时候,C++编译器会给这个类生产一个虚函数表。在这个类的对象里面会自动生成一个成员_vfptr, _vfptr就是指向虚函数表的一个指针。通过这个虚函数表,C++就可以支持多态。至于虚函数表的工作机理,此处就不做探讨了。
通常我们建议把析构函数搞成虚函数,这个是有好处的。不然很多时候会发现子类的析构函数没有被调用,也就是造成了内存泄漏。但是世事无绝对,有时候把析构函数搞成虚函数也会带来一点问题,Effective C++书里面有介绍,大家可以参考。
总之,我们只要搞清楚原理,就可以根据实际情况来取舍了。
- C++-----虚析构函数
- C++----虚析构函数
- C++【浅谈虚析构函数】
- C++_虚析构函数
- 【c++】虚析构函数
- (C++)虚析构函数
- C++---------之--------【虚析构函数】
- 【C/C++】C++虚析构函数的作用
- [C/C++]C函数
- 【C++】正确使用虚析构函数
- c++------------之---【虚析构函数应用】
- <C++>析构函数、虚析构函数和构造函数
- c 函数
- C函数
- C 函数
- C函数
- 【C++】函数
- C 函数
- oracle sql developer 如何支持多个窗体,打开多张表,多个tab,同时查看多个数据表
- windows系统文件快速查询(全)
- C&C++之标准库
- python装饰器
- Android地图开发之Overlay应用(高德)
- C++ 虚析构函数
- 控件为何不能自动装载?--全面总结
- MS SQL Server收缩日志文件
- C++之命名空间
- 利用COM组件IPicture读取jpg、gif、bmp图片文件数据和显示图片的两个函数
- eventfd函数详解
- 流年的最新伤感日志:年轻的时候,会轻狂
- DB2对decimal类型的数据进行char()时会在前面加0
- C++