C++基类的析构函数定义为虚函数的原因
1:每个析构函数只会清理自己的成员(成员函数前没有virtual)。
2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类的析构函数要定义为虚函数;
基类指针可以指向派生类的对象(多态),如果删除该指针delete[]p,就会调用该指针指向的派生类的析构函数,而派生类的对象又会自动调基类的成员函数,这样就会把派生类的对象释放,如果基类的析构函数没有定义成虚函数,则编译器实现的静态绑定,在删除基类的指针,只会释放基类的析构函数而不会释放派生类的成员函数,此时会导致释放内存不完全,就会导致内存泄露的问题。
一:派生类指针指向派生类的对象
class Base
{
public: Base()
{ cout << "Base()" << endl; }
virtual ~Base()
{
cout << "~Base()" << endl;
}
};
class Driver :public Base
{
public: Driver()
{
cout << "Driver()" << endl;
}
~Driver()
{
cout << "~Driver()" << endl;
}
};
void Test()
{
Driver*pd = new Driver;
delete pd;
}
结果:
base()
Driver()
~Driver()
~Base()
派生的指针指向派生类的对象,释放p的过称是先释放派生类的析构函数,再释放基类的析构函数
二:基类的指针指向派生类的对象(无virtual)
class Base
{ public: Base()
{
cout << "Base()" << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
}; class Driver :public Base
{ public: Driver()
{
cout << "Driver()" << endl;
}
~Driver()
{
cout << "~Driver()" << endl;
}
};
void Test()
{
Base *pd = new Driver;
delete pd;
}
运行结果:
Base()
Driver()
~Basce()
当基类的指针指向派生类的对象的成员,释放pd的过程是:只是释放了基类的资源,而没有调用派生类的析构函数;这样的删除只能删除基类对象,而不能删除派生类的对象,造成内存泄露;
在公有继承中,基类对派生类的对象的操作,只能影响哪些继承的成员,如果想要基类对非继承进行操作,则要把这个基类函数定义为虚函数;
C++基类的析构函数定义为虚函数的原因的更多相关文章
- C++中为什么要将析构函数定义成虚函数
构造函数不可以是虚函数的,这个很显然,毕竟虚函数都对应一个虚函数表,虚函数表是存在对象内存空间的,如果构造函数是虚的,就需要一个虚函数表来调用,但是类还没实例化没有内存空间就没有虚函数表,这根本就是个 ...
- 【转载】 C++多继承中重写不同基类中相同原型的虚函数
本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...
- 读书笔记 effective c++ Item 7 在多态基类中将析构函数声明为虚析构函数
1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeepe ...
- C++析构函数定义为虚函数(转载)
转载:http://blog.csdn.net/alane1986/article/details/6902233 析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数.如果析构函数不是虚函 ...
- C++多态性中基类析构函数声明为虚函数
在用基类指针指向派生类时, 在基类析构函数声明为virtual的时候,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数. 在基类析构函数没有声明为virtual的时候,delete ...
- 构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数
一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的.问题出来了,假设构造函数 ...
- 【C++】C++中基类的析构函数为什么要用virtual虚析构函数?
正面回答: 当基类的析构函数不是虚函数,并且基类指针指向一个派生类对象,然后通过基类指针来删除这个派生类对象时,如果基类的析构函数不是虚析构函数,那么派生类的析构函数就不会被调用,从而产生内存泄漏 # ...
- C++构造与析构函数中调用虚函数的问题
前些天想把以前写的内存池算法重写一遍,跨平台是第一目标,当时突发奇想,因为不愿意做成一大堆#if..#end,所以想利用C++的多态性,但是怎么让内存池完好退出却没想到自认为完美的方案.但是一个很偶然 ...
- C++中基类的析构函数为什么要用virtual虚析构函数
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...
随机推荐
- Vue学习资料
1. {{ msg }}插值表达式. v-text:将数据插入到页面中,没有闪烁问题. v-cloak:通过style属性选择器的方式display:none:防止闪烁问题. v-html:将标签解析 ...
- MySQL安装的挫折之路
由于对MySQL卸载的不干净,mysql 的MySQL Connector Net/xxx无法卸载,后期重装无法成功.所以只能采用zip 安装https://www.cnblogs.com/Micha ...
- The Minimum Cycle Mean in a Digraph 《有向图中的最小平均权值回路》 Karp
文件链接 Karp在1977年的论文,讲述了一种\(O(nm)\)的算法,用来求有向强连通图中最小平均权值回路(具体问题请参照这里) 本人翻译(有删改): 首先任取一个节点 \(s\) ,定义 \(F ...
- docker 部署 java 项目
Docker Docker官方网址: https://docs.docker.com/ 英文地址 Docker中文网址: http://www.docker.org.cn/ 中文地址 Docker是 ...
- JSP内置对象——pageContext对象和config对象
它对应的常用方法有: 现在,我新建一个“pageContext.jsp”页面,可以获得“session_page1.jsp”这个页面中保存的用户名: pageContext.jap: session_ ...
- Netatalk CVE-2018–1160 越界访问漏洞分析
编译安装 首先下载带有漏洞的源代码 https://sourceforge.net/projects/netatalk/files/netatalk/3.1.11/ 安装一些依赖库(可能不全,到时根据 ...
- PopupWindow 弹出时背景变暗
下面的PopupWindow 的高是相对于屏幕高设计,宽是获取的某一个控件的宽设置,位置位于某控件的上方,红色部分是设置弹出时屏幕变暗的. //设置contentView View contentV ...
- js replace替换 忽略大小写问题
实现就是控制台的内容“abc”,但是后台返回的是“ABC”,这个时候在前台遍历,需要将后台返回的在控制台标红. 当然控制台可以是 abc Abc等大小写混合,以下代码都可替换. var flagnew ...
- CentOS7的/tmp目录自动清理规则
CentOS6以下系统(含)使用watchtmp + cron来实现定时清理临时文件的效果,这点在CentOS7发生了变化. 在CentOS7下,系统使用systemd管理易变与临时文件,与之相关的系 ...
- [cb]Unity 关卡编辑器 开发
关卡编辑器 关卡编辑器插件开发日记 1. Apply to Prefab [替换Prefab] if (GUILayout.Button("Apply Collider To Prefab& ...