Virtual Destructor
Deleting a derived class object using a pointer to a base class that has a non-virtual destructor results in undefined behavior. To correct this situation, the base class should be defined with a virtual destructor.
Source: https://www.securecoding.cert.org/confluence/display/cplusplus/OOP34-CPP.+Ensure+the+proper+destructor+is+called+for+polymorphic+objects
For example, following program results in undefined behavior. Although the output of following program may be different on different compilers, when compiled using Dev-CPP, it prints following.
Constructing base
Constructing derived
Destructing base
1 // A program without virtual destructor causing undefined behavior
2 #include<iostream>
3
4 using namespace std;
5
6 class base
7 {
8 public:
9 base()
10 {
11 cout<<"Constructing base \n";
12 }
13 ~base()
14 {
15 cout<<"Destructing base \n";
16 }
17 };
18
19 class derived: public base
20 {
21 public:
22 derived()
23 {
24 cout<<"Constructing derived \n";
25 }
26 ~derived()
27 {
28 cout<<"Destructing derived \n";
29 }
30 };
31
32 int main(void)
33 {
34 derived *d = new derived();
35 base *b = d;
36 delete b;
37 getchar();
38 return 0;
39 }
Making base class destructor virtual guarantees that the object of derived class is destructed properly, i.e., both base class and derived class destructors are called.
For example, following program prints:
Constructing base
Constructing derived
Destructing derived
Destructing base
1 // A program without virtual destructor causing undefined behavior
2 #include<iostream>
3
4 using namespace std;
5
6 class base
7 {
8 public:
9 base()
10 {
11 cout<<"Constructing base \n";
12 }
13 virtual ~base()
14 {
15 cout<<"Destructing base \n";
16 }
17 };
18
19 class derived: public base
20 {
21 public:
22 derived()
23 {
24 cout<<"Constructing derived \n";
25 }
26 ~derived()
27 {
28 cout<<"Destructing derived \n";
29 }
30 };
31
32 int main(void)
33 {
34 derived *d = new derived();
35 base *b = d;
36 delete b;
37 getchar();
38 return 0;
39 }
As a guideline, any time you have a virtual function in a class, you should immediately add a virtual destructor (even if it does nothing). This way, you ensure against any surprises later.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
转载请注明:http://www.cnblogs.com/iloveyouforever/
2013-11-26 21:06:36
Virtual Destructor的更多相关文章
- [C++] Virtual Destructor(虚析构函数)
Without Virtual Destructor(虚析构函数) class A{ public: ; A() { cout <<"A()..."<< e ...
- [CareerCup] 13.6 Virtual Destructor 虚析构函数
13.6 Why does a destructor in base class need to be declared virtual? 这道题问我们为啥基类中的析构函数要定义为虚函数.首先来看下面 ...
- effective c++ 条款7 declare virtual destructor for polymophyc base class
这似乎很明显. 如果base class的destructor不是virtual,当其derived class作为基类使用,析构的时候derived class的数据成员将不会被销毁. 举个例子 我 ...
- C++ 虚析构(virtual destructor)原理
注意:本文仅为个人理解,可能有误! 先看一段代码: #include <iostream> using namespace std; class CBase{ public: CBase( ...
- 《Effective C++》条款14 总是让base class拥有virtual destructor
有时,一个类想跟踪它有多少个对象存在.一个简单的方法是创建一个静态类成员来统计对象的个数.这个成员被初始化为0,在构造函数里加1,析构函数里减1.(条款m26里说明了如何把这种方法封装起来以便很容易地 ...
- 为什么内联函数,构造函数,静态成员函数不能为virtual函数
http://blog.csdn.net/freeboy1015/article/details/7635012 为什么内联函数,构造函数,静态成员函数不能为virtual函数? 1> 内联函数 ...
- 条款7:为多态基类声明virtual析构函数
C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的.其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用. # ...
- Memory Layout for Multiple and Virtual Inheritance
Memory Layout for Multiple and Virtual Inheritance(By Edsko de Vries, January 2006)Warning. This art ...
- why pure virtual function has definition 为什么可以在基类中实现纯虚函数
看了会音频,无意搜到一个frameworks/base/include/utils/Flattenable.h : virtual ~Flattenable() = 0; 所以查了下“纯虚函数定义实现 ...
随机推荐
- 关于docker中容器可以Ping通外网,真机无法Ping通容器的问题
首先我们要知道整体的框架结构,docker是我们安装在centos7上的,而centos7是安装在vmware上.其中docker中还有若干容器运行. 整体框架图如下: 我们将它分为两部分,一部分是d ...
- 使用psftp向服务器上传文件
老师刚才说想用psftp上传文件到服务器,我之前没听过,学了一下,总结下.我们用PSFTP主要也就是上传和下载. PSFTP是PuTTY SFTP客户端,用于本地与服务器间安全传输文件(使用SSH连接 ...
- 集合之Map接口
Map接口概述 Map与Collection并列存在.用于存储具有映射关系的数据 : key-value Map 中的 key 和 value 都可以是任何引用类型的数据 Map 中的 key 用Se ...
- Linux环境下安装、配置Redis
linux下安装redis 官网下载链接:https://redis.io/download 安装 下载redis压缩包 1.选择Stable(5.0)下的Download 5.0.0 链接进行下载 ...
- 大数据SQL中的Join谓词下推,真的那么难懂?
听到谓词下推这个词,是不是觉得很高大上,找点资料看了半天才能搞懂概念和思想,借这个机会好好学习一下吧. 引用范欣欣大佬的博客中写道,以前经常满大街听到谓词下推,然而对谓词下推却总感觉懵懵懂懂,并不明白 ...
- mybatis中批量插入的两种方式(高效插入)
MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用 ...
- MySQL用limit代替SQL Server :top
mysql 中不支持top,而是用limit代替 若要查询前10条记录,mysql用limit 10 LIMIT可以实现top N查询,也可以实现M至N(某一段)的记录查询,具体语法如下: SELEC ...
- X-MagicBox-820的luatOS之路连载系列4
上次说到定位成功后,显示的数据准确性问题.专门查询了下我所在地区的经纬度信息. MagicBox的显示数据是这样的: 网络上查到的经纬度数据是这样的: 可以看出定位精度还可以,毕竟我这个查询的数据没有 ...
- [luogu7417]Minimizing Edges P
令$e_{G}(a)$和$o_{G}(a)$分别表示在图$G$中从1到$a$的长度为奇数/偶数的最短路(若该类最短路不存在则为$\infty$),不难得到有以下结论--$f_{G}(a,b)=\beg ...
- Windows系统及硬件信息读取
Windows桌面端开发常常会需要读取系统信息或硬件信息作为用户标识,比如用于确认该设配是否已经激活程序.也可以使用随机生成的UUID来作为唯一标识,但是如果重装系统或重装软件都有可能导致标识丢失,因 ...