为什么析构函数常常必须为虚函数
来源:互联网 发布:编程语言pascal 编辑:程序博客网 时间:2024/05/24 05:39
首先来看下面很简单的代码
#include<iostream>using namespace std;class Base{private : int ma;public: Base(int n):ma(n){cout<<"Base()"<<endl;}//构造函数 void virtual show(){cout<<"ma="<<ma<<endl;} ~Base(){cout<<"~Base"<<endl;}//析构函数};class Derive: public Base{private : int mb;public: Derive(int n):Base(n){cout<<"Derive()"<<endl;}//构造函数 void virtual show(){cout<<"mb="<<mb<<endl;} ~Derive(){cout<<"~Derive()"<<endl;}//析构函数};int main(){ Base*p = new Derive(10); delete p; return 0;}
运行结果:
Base()
Derive()
~Base
请按任意键继续…
虽然能运行,但是很明显,存在内存泄漏,p指向的是一个派生类对象,但是释放的时候,只是把基类给释放掉了,那么派生类自己的数据呢,并没有释放,依然在堆上,造成内存的泄漏。
如果把基类的析构函数改为虚函数:
#include<iostream>using namespace std;class Base{private : int ma;public: Base(int n):ma(n){cout<<"Base()"<<endl;}//构造函数 void virtual show(){cout<<"ma="<<ma<<endl;} virtual ~Base(){cout<<"~Base"<<endl;}//析构函数};class Derive: public Base{private : int mb;public: Derive(int n):Base(n){cout<<"Derive()"<<endl;}//构造函数 void virtual show(){cout<<"mb="<<mb<<endl;} ~Derive(){cout<<"~Derive()"<<endl;}//析构函数};int main(){ Base*p = new Derive(10); delete p; return 0;}
运行结果:
Base()
Derive()
~Derive()
~Base
请按任意键继续…
不存在内存泄漏。
把基类的析构函数改为虚函数,那么delete p 的时候调用析构函数,因为基类的析构函数为虚函数,此时派生类的析构函数就变成了虚函数,调用虚函数时,就要查找vftable(虚函数表),此时在派生类对象的虚函数表里,派生类的虚析构函数,把基类的析构函数给覆盖了。虚函数表的最上面的第一行表示RTTI运行时的类型状态,此时为派生类,于是调用派生类的析构函数。
于是调用派生类的析构函数,系统先调用基类的析构函数,再调用派生类的析构函数,就不会存在内存的泄漏现象。
用一句话概括为什么使用虚析构函数:在使用多态,而且基类的指针指向堆上的对象时,调用delete释放对上的对象,防止内存泄漏。
0 0
- 为什么析构函数常常必须为虚函数
- 为什么析构函数常常声明为虚函数
- 为什么析构函数常常是虚函数
- c++ 为什么析构函数必须声明为虚函数
- 为什么构造函数不可以被声明为虚函数而析构函数有时候必须声明为虚函数
- 为什么基类的析构函数必须为虚函数的原因-个人理解
- 在C++中,为什么有时析构函数必须写为虚函数
- C++中为什么有时基类的析构函数必须写为虚函数
- 为什么虚函数必须是非静态成员函数 构造函数可以为static
- 为什么虚函数必须是非静态成员函数 构造函数能为static吗?
- 为什么虚函数必须是非静态成员函数 构造函数可以为static
- 为什么虚函数必须是非静态成员函数 构造函数能为static吗?
- 为什么虚函数必须是非静态成员函数 构造函数能为static吗?
- 为什么构造函数不能声明为虚函数,析构函数可以声明为虚函数
- 为什么构造函数不能为虚函数,而析构函数可以为虚函数?
- 为什么构造函数不能为虚函数,而析构函数可以为虚函数
- 为什么析构函数常声明为虚函数
- C++析构函数为什么要为虚函数
- Volley框架网络访问String,JsonObject,JsonArray
- 坑爹的 CentOS7.1网卡设置
- IT 运行在云端,而云运行在 Linux 上
- 第三周项目4——顺序表应用1
- 回溯法解决0_1背包问题(迭代和递归)
- 为什么析构函数常常必须为虚函数
- 前端解决跨域问题的8种方案(最新最全)
- 控件测试的一般方法
- 博弈论游戏之猎人与虎
- 加载html页面的同时加载方法
- 涂鸦移动面试纪要
- Android SDK Manager 开发组件 下载慢解决方案
- paypal的即时付款通知参数列表(PDT)
- 数据库优化50法