C++ 虚析构(virtual destructor)原理
注意:本文仅为个人理解,可能有误!
先看一段代码:
#include <iostream>
using namespace std; class CBase{
public:
CBase()
{
cout<<"CBase construct ... "<<endl;
}
virtual ~CBase()
{
cout<<"CBase destructor ... "<<endl;
}
}; class CSon : public CBase{
public:
CSon(){
cout<<"CSon construct ... "<<endl;
}
~CSon(){
cout<<"CSon destructor ... "<<endl;
}
}; void test()
{
CBase* pObj = new CSon();
delete pObj;
} int main(int argc,char* argv[])
{
test();
return 0;
}
上面这段代码,输出:
CBase construct ...
CSon construct ...
CSon destructor ...
CBase destructor ...
大家都能理解,而将virtual ~CBase() 的virtual 去掉, 将输出:
CBase construct ...
CSon construct ...
CBase destructor ...
大家将看到,子类的析构函数没有被调用。
那为什么加了virtual就会调用子类的析构函数呢?这是本文的主题。
首先要理解几个概念:
0,在没有加virtual的时候,这个继承体系没有任何虚函数,所以CSon,CBase均不含虚函数表。
1,子类构造函数/析构函数会自动调用父类的构造/析构函数(编译期决定);
2,编译期的常识:
CBase* pObj = new CSon();
这句相当于
CSon* pTmp = new CSon();
CBase* pObj = (CBase*)pTmp;
前一句中编译器是直接调用CSon::CSon()返回位pTmp,pTmp赋值给pObj。因而生成的pObj实际上是CSon对象,但pObj的类型被记录为CBase类型。
delete pObj;
delete时编译器只知道这个pObj是CBase类型 。
情况一,在CBase的析构函数为非virtual时:
编译器在编译“delete pObj;” 时根据pObj的类型是CBase调用CBase::~CBase(),不会调用子类析构函数。
情况二,在CBase的析构函数为virtual时:
此时继承体系中有一个虚函数表,这个时候,编译器就不会直接调用CBase::~CBase(),而是调用call pObj->pvtable-> vtable[0],又pObj这个对象实际上是CSon对象,所以调用流程如下:
delete pObj; –> call pObj->pvtable-> vtable[0] –> CSon::~CSon()
而在CSon::~CSon中会自动递归调用父类的析构函数,所以全部资源释放完成。
关于动态绑定部分,可以参见如下两张图:
1,CBase初始化完毕:

2,CSon初始化完毕:

C++ 虚析构(virtual destructor)原理的更多相关文章
- [C++] Virtual Destructor(虚析构函数)
Without Virtual Destructor(虚析构函数) class A{ public: ; A() { cout <<"A()..."<< e ...
- C++中虚析构的作用
为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用. 基本概念: 析构函数是用来回收对象的: 虚析构函数是析构函数的一种: 基类是一类对象共有属性的抽象.比如,猫和狗都是动物,都会 ...
- C++ - 复制(copy) 和 虚复制(virtual copy) 的 区别
复制(copy) 和 虚复制(virtual copy) 的 区别 本文地址: http://blog.csdn.net/caroline_wendy/article/details/16120397 ...
- C++的虚析构
最近准备复习一遍所有的知识点,先从基础开始做起,用几分钟写个继承和析构吧. 父类为A,子类为B,代码如下: class A { public: A() { cout << "构造 ...
- C++虚函数的工作原理
静态绑定与动态绑定 讨论静态绑定与动态绑定,首先需要理解的是绑定,何为绑定?函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定. 理解了绑定后再理解静态与动态. 静态绑定:指在程序 ...
- C++中虚函数的作用和虚函数的工作原理
1 C++中虚函数的作用和多态 虚函数: 实现类的多态性 关键字:虚函数:虚函数的作用:多态性:多态公有继承:动态联编 C++中的虚函数的作用主要是实现了多态的机制.基类定义虚函数,子类可以重写该函数 ...
- C++——虚析构
目的: //只执行了 父类的析构函数//向通过父类指针 把 所有的子类对象的析构函数 都执行一遍//向通过父类指针 释放所有的子类资源 方法:在父类的析构函数前+virtual关键字 #define ...
- C++ //虚析构和纯虚析构
1 //虚析构和纯虚析构 2 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 clas ...
- Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息
Delphi之静态方法,虚方法virtual,动态dynamic,抽象abstract,消息 http://www.cnblogs.com/zhwx/archive/2012/08/28/266055 ...
随机推荐
- [Python爬虫] 之十七:Selenium +phantomjs 利用 pyquery抓取梅花网数据
一.介绍 本例子用Selenium +phantomjs爬取梅花网(http://www.meihua.info/a/list/today)的资讯信息,输入给定关键字抓取资讯信息. 给定关键字:数字: ...
- 淘宝JAVA中间件Diamond
以下是转载自网上资料,但是根据步骤可以搭建出diamond配置中心服务器. 项目中需要用到diamond的理由是, 项目中使用了很多定时任务和异步任务.而且这些定时任务和异步任务都是分布式的安排在多个 ...
- 爪哇国新游记之二十八----从url指定的地址下载文件到本地
package download; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; ...
- select * from (select user())a 为什么是查询user()的意思?
步骤:1.先查询 select user() 这里面的语句,将这里面查询出来的数据作为一个结果集 取名为 a2.然后 再 select * from a 查询a ,将 结果集a 全部查询出来
- A.0 B.1 C.2 D.3
17. 以下哪个不是广告平台? A.Admob B.Domob C.InMobi D.TalkingData 错误 应该选择:D.TalkingData 10. 哪个不是免费的工具? A.Xcode ...
- oracle data file header replace(測)
SQL> create tablespace rm_tbs datafile 'f1.dbf' size 10m; Tablespace created. SQL> select file ...
- 一站式学习Wireshark(转载)
一站式学习Wireshark(一):Wireshark基本用法 2014/06/10 · IT技术 · 4 评论 · WireShark 分享到: 115 与<YII框架>不得不说的故事— ...
- Cocos2d-x 3.x版2048游戏开发
Cocos2d-x 3.x版2048游戏开发 本篇博客给大家介绍怎样高速开发2048这样一款休闲游戏,理解整个2048游戏的开发流程.从本篇博客你将能够学习到下面内容: 这里注明一下,本教程来自极客学 ...
- jQuery Ajax 学习(转)
Ajax全称:Asynchronous JavaScript and XML(异步的JavaScript和XML)特点:在不必刷新整个网页的情况下实现局部更新,带来更好的用户体验.因为XMLHttpR ...
- svn Couldn't open rep-cache database
出现这样的错误原因是因为 问题一 开始出现错误:The database disk image is malformed 解决方案:http://www.cnblogs.com/chen110xi/p ...