C++中虚析构函数的作用及其原理分析
参考http://blog.csdn.net/xiamentingtao/article/details/55517203
C++中的虚析构函数到底什么时候有用的,什么作用呢。
一.虚析构函数的作用
总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的.
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:
#include<iostream>
using namespace std;class ClxBase
{public:ClxBase() {};virtual ~ClxBase() { cout<<"delete ClxBase"<<endl; };virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };};class ClxDerived : public ClxBase
{public:ClxDerived() {};~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };};int main(int argc, char const* argv[])
{ClxBase *pTest = new ClxDerived;pTest->DoSomething();delete pTest;return 0;
}
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
没有调动子类的析构函数
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
总结一下虚析构函数的作用:
(1)如果父类的析构函数不加virtual关键字
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
(2)如果父类的析构函数加virtual关键字
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。
二.虚析构函数的原理分析
#include<iostream>
using namespace std;class Base
{
public:Base(){cout<<"create Base"<<endl;}virtual ~Base(){cout<<"delete Base"<<endl;}
};class Der : public Base
{
public:Der(){cout<<"create Der"<<endl;}~Der(){cout<<"Delete Der"<<endl;}
};
int main(int argc, char const* argv[])
{Base *b = new Der;delete b;return 0;
}
从创建讲起,用gdb调试你会发现,
(1)先调用父类的构造函数,再调用子类的构造函数,
这里有一个问题:父类的构造函数/析构函数与子类的构造函数/析构函数会形成多态,但是当父类的构造函数/析构函数即使被声明virtual,子类的构造/析构方法仍无法覆盖父类的构造方法和析构方法。这是由于父类的构造函数和析构函数是子类无法继承的,也就是说每一个类都有自己独有的构造函数和析构函数。
(2)而由于父类的析构函数为虚函数,所以子类会在所有属性的前面形成虚表,而虚表内部存储的就是父类的虚函数
即使子类也有虚函数,但是由于是单继承,所以也只有一张虚表,这在上一篇博客多态中讲到过。
执行 Base *b = new Der;之后b的最终形态
(3)当delete父类的指针时,由于子类的析构函数与父类的析构函数构成多态,所以得先调动子类的析构函数;之所以再调动父类的析构函数,是因为delete的机制所引起的,delete 父类指针所指的空间,要调用父类的析构函数。
所以结果就是这样
C++中虚析构函数的作用及其原理分析相关推荐
- C++中虚析构函数的作用及原理
C++中虚析构函数的作用及原理 先测测你哟,上代码
- C++中虚析构函数的作用
#include <iostream> using namespace std;class Base{ public:Base(){};~Base(){cout<<" ...
- [C++]虚析构函数的作用
C++中的虚析构函数到底什么时候有用的,什么作用呢. 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的.也就说虚析构函数使得在删除指向子类对象 ...
- c++ 虚析构函数的作用
文章目录 构造析构顺序 构造函数和析构函数的调用顺序 定义 原因 作用 代码 代码 构造析构顺序 构造函数和析构函数的调用顺序 构造函数的调用顺序: 当建立一个对象时,首先调用基类的构造函数,然后调用 ...
- C++ 之虚析构函数的作用
虚析构函数的作用: 析构函数是可以声明为虚函数的,如果基类指针指向一个new生成的派生类对象,通过delete作用于基类指针删除派生类对象时,有以下两种情况: 如果基类析构函数不为虚析构函数,则只会调 ...
- 2020-12-08图腾柱驱动的作用与原理分析
图腾柱驱动的作用与原理分析 电子设计•作者:电子设计 • 2018-10-08 07:27 • 65048次阅读 0 由于此结构画出的电路图有点儿像印第安人的图腾柱,所以叫图腾柱式输出(也叫图腾式输 ...
- Cpp 对象模型探索 / 多重继承下基类指针释放子类对象的原理说明(虚析构函数的作用)
源码 #include <iostream>class Base1 { public:virtual void func_1_1(){ std::cout << "B ...
- C++中虚析构函数和纯虚函数的作用
一. 虚析构函数 为了能够正确的调用对象的析构函数,一般要求具有层次结构的顶级类定义其析构函数为虚函数.因为在delete一个抽象类指针时候,必须要通过虚函数找到真正的析构函数. class Base ...
- C++中的虚析构函数的作用
事实上,虚析构函数,就是虚的析构函数,也就是析构函数具有了虚函数的性质. 在C++开发中,用来做基类的类的析构函数一般都是虚函数,为什么要这样做,下面来进行以下说明: 下面程序中定义两个类,公有继承: ...
最新文章
- [Eclipse]GEF入门系列(七、XYLayout和展开/折叠功能)
- 运维笔记--postgresql占用CPU问题定位
- TCP 通信过程中各步骤的状态
- 【Python】编程笔记7
- USEFORM,USERES详解
- 15分钟内开始使用Amazon Web Services和全自动资源调配
- react不同环境不同配置angular_前端问题集:vue配置环境-给不同的环境配不同的打包命令...
- 如何在linux安装mysql7版本的,如何在linux下用tar方式安装Mysql5.7版本
- Intellij idea利用Statistic插件统计项目代码行数
- 前端 JavaScript 之『节流』的简单代码实现
- oracle支持ipv6,准备现有的网络以支持 IPv6
- linux zip命令收藏
- 梦之翼网络LAMP技术博客正式成立!
- 国家统计局 省市区 数据爬取
- 小程序中自定义组件、父子传值的具体步骤(秒懂)
- LC053-最大子序和
- 《月亮与六便士》的读后感作文3000字
- 模仿百思不得姐项目开发总结
- DLL load failed while importing _cvxcore解决办法
- 【宝贝,既然你爱了,那就敞开心扉】
热门文章
- 【STM32】基于F103C8T6和ESP01远程控制灯光开关(SG90舵机控制)
- slate rhi_Slate的URL正在改头换面
- i710750h和i79750h对比哪个好 i7 10750h和i7 9750h性能差距
- TextRank关键词提取算法
- 老王赛马!!!(题目有漏洞哦)
- 可以一键生成crud的php框架,一键生成CRUD - FastAdmin框架文档 - FastAdmin开发文档
- PS丨PS修改标尺单位
- 蔬菜大棚原理_温室大棚的工作原理及温室大棚分类
- 【Linux后端服务器开发】TCP通信设计
- java作业:用GUI实现一个科学计算器的设计