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; 所以查了下“纯虚函数定义实现 ...
随机推荐
- webpack 打包样式资源
webpack 打包样式资源 webpack.config.js配置文件内容为: // 用来拼接绝对路径的方法 const {resolve} = require('path') module.exp ...
- java eclipse调试提示Source not found 或 一闪而过 解决方法
Web工程Eclipse debug方式启动,在断点的位置被成功拦截,但是没有跳转到工程的代码处,提示如下: 当然这个时候如果我继续按F5的话呢,程序又会接着正常运行了.到这里那就是说程序本身是没有 ...
- sui Mobile 试玩
.... 突然就用上这东西还不熟悉就写了一个页面而已 <a class="open-popup button pull-right create-actions" id=&q ...
- [atARC088F]Christmas Tree
合并具有交换律,因此即将一个连通块(初始为空)与一条链合并(其中各选1点,初始直接替换) 把插入改为染色,等价于对树上的一条链(包括点和边)染色,其中恰好有1个已经被染色的点(初始任意) 对于&quo ...
- [atAGC049E]Increment Decrement
由于每一个操作的逆操作都存在,可以看作将$a_{i}$全部变为0的代价 先考虑第一个问题,即对于确定的$a_{i}$如何处理 如果仅能用第2种操作,定义点$i$的代价为以$i$为左端点或以$i-1$为 ...
- oracle 创建空间索引
1. 首先进行查询,判断数据是否已经建立相应的空间元数据 select * from user_sdo_geom_metadata t where t.table_name like '%表名%'; ...
- mybatis判断集合长度
使用mybatis框架在写sql的时候碰到一个异常: 1064 - You have an error in your SQL syntax; check the manual that corres ...
- 卸载.net 5.0后使用dotnet提示Found .NET Core SDK
之前安装了预览版本的vs2019后试了下,然后卸载了.但发现控制台执行dotnet相关命令提示Found .NET Core SDK, but did not find dotnet.dll at [ ...
- msyql_union
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中.多个 SELECT 语句会删除重复的数据. 语法 MySQL UNION 操作符语法格式: SELECT ...
- docker 使用加速器下载
因为docker官网的镜像地址docker.hum.com是在国外的 所以下载速度比较慢,国内有一些镜像源是比较快的,内容是和docker官网的一致 常用的加速器有 docker-cn 阿里云加速器 ...