多态基类与虚析构函数
来源:互联网 发布:液晶清洁液-知乎 编辑:程序博客网 时间:2024/05/17 13:41
假设我们有一个基类A,很不幸的,A的析构函数是一个non-virtual。同时我们有一个派生类B,它派生自A。
我们定义了一个A类型指针,它指向的实际对象是B:
A * ptr = new B;
然后在程序的某处,我们不再需要B了,我们将指针ptr delete掉:
delete ptr;
注意new永远要和delete成队出现,除非你使用智能指针。这时由于A的析构函数是non-virtual,一个悲剧诞生:
C++中明确指出,当派生类对象经由一个基类指针被删除,而该基类带着一个non-virtual析构函数,其结果未定义--实际执行时通常发生的是对象的派生部分没有被销毁。也就是B对象部分发生内存泄漏。
问题的解决办法就是为多态基类A声明一个虚析构函数。简单吧,另一个更加通用的准则是:如果一个类拥有至少一个虚函数,那么这个类也应该要有一个虚析构函数,因为类中拥有虚函数已经表明该类将作为基类来使用,期待子类实现自己的虚函数,此时基类应该为析构函数作virtual声明。
反过来的另一条准则是,如果一个类不想作为基类,那么不要为其声明任何成员函数做virtual声明。为啥?virtual有代价啊。为了支持多态机制,编译器为类对象安插一个虚表指针,同时类也多了一张虚函数表。如果我们的类本来只有一个int类型的数据成员,在32bit机器上,sizeof(类)为4,而加了vptr后,sizeof(类)为8,类对象的大小整整翻了100%!
当然,就算我们的编程遵循了上面的准则,有时候还有有些许错误。切勿不要以没有任何虚函数的类作为基类。有时候由于我们的粗心大意或者在毫不知情的情况下我们可能会干这种事情。例如,我们想实现一个自己的容器MyList,并想借助STL的list来实现:
class MyList :public list{ //...};
那么内存泄漏的问题又来了,STL中的list并不打算作为一个基类来使用,因此它的析构函数也不是一个virtual。类似的还有string、stl的vector、set、unordered_map等等。
好在,C++11 提供了final关键字,对于不想被继承的类,我们在其定义时加上final关键字:
class Super final{ //......};
这样试图继承super时编译器将会报错。
- 多态基类与虚析构函数
- 构造函数与虚析构函数
- 构造函数与虚析构函数
- 虚函数与虚析构函数
- 虚函数与虚析构函数
- 基础备忘:多态基类与虚析构函数
- 虚构造函数与虚析构函数
- 虚析构函数与非虚析构函数问题!
- C++虚析构函数与纯虚析构函数
- 合成析构函数与虚析构函数
- C++虚函数与虚析构函数
- C++虚函数与虚析构函数
- C++虚析构函数与纯虚析构函数
- C++基础---虚析构函数与纯虚析构函数
- 多态、虚函数与虚析构函数
- 虚函数与虚析构函数原理
- 虚析构函数与内存泄露
- 虚析构函数与内存泄露
- MTTR是什么?或者说为什么别给婴儿喝白兰地
- 3.4wait的条件发生变化导致逻辑错误
- struts2标签和jstl标签混和使用
- 来,让我们写一个网络爬虫,下载页面上所有的照片吧!
- 统一初始化语法
- 多态基类与虚析构函数
- 如何来写好一个赋值运算符函数
- 《将博客搬至CSDN》
- 如何判断循环链表
- Python流控制- 逻辑运算符
- 浅谈malloc()与free()
- JVM调优
- 自定义ListView下拉刷新和上拉加载
- Android Volley框架的几种post提交请求方式