析构函数virtual与非virtual区别 [转]
作为通常的原则,如果一个类定义了虚函数,那么它的析构函数就应当是virtual的。因为定义了虚函数则隐含着:这个类会被继承,并且会通过基类的指针指向子类对象,从而得到多态性。 这个类可能会被继承,并且会通过基类的指针指向子类对象”,因此基类的析构函数是否为虚将决定子类的对象是否被析构
示例代码:
#include <iostream.h> struct A
{
virtual ~A() {cout<<"~A()\n";}
}; struct B: public A
{
~B() {cout<<"~B()\n";}
}; void main()
{
A* p = new B;
delete p;
}
如果 A的析构函数不是virtual的,那么此时就不是先调用B的析构函数再调用A的析构函数。
Output:
~A();
如果A 的析构函数为virtual,则先~B(),再~A()
Output:
~B();
~A();
类如果会被派生的话,析构函数一般都应该定义为virtual的,主要不是防止内存泄露,而是为了正确的析构。如果是个封闭类(即不再被派生),就不要定义为virtual的。虚函数毕竟耗费较大的。
不用virtual 的几种情况:
1、作为非公有基类。仅作为 private base class 使用的 class 不需要使用虚拟析构函数
2、不作为接口使用的基类。
3. 如果你可以保证这个类不被public继承(private/protected继承的话,在非friend函数/类中就无法用基类指针指向派生类了)
4. 如果它的所有派生类(包括派生类的派生类)的析构函数都是trivial的(这里的trivial指的是在程序员的层次什么事也不做)
5. 如果不需要用基类的指针指向派生类的对象
在这五种情况下,不把析构函数声明为virtual都是可以的,何况效率会高一些——但前提是你得保证前提的成立——不过这些保证常常是很难100%的:谁能保证别人在派生你的类的时候,析构函数是trivial的,或者别人不用你提供的基类的指针指向派生类对象?这些常常是很难得到保证的。
声明基类的析构函数为virtual并非总是为了防止memory leak 另外这也只是作为一般的原则(基类中有虚函数则把其析构函数声明为virtual)。如果你的析构函数什么事也不作,从效果上来说,不声明为virtual也无妨.
析构函数virtual与非virtual区别 [转]的更多相关文章
- C++-基类的析构函数为什么要加virtual虚析构函数(转)
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...
- C#中virtual与abstract的区别
C#中virtual与abstract的区别 C#的virtual & abstract经常让人混淆,这两个限定词都是为了让子类进行重新定义,覆盖父类的定义.但是用法上差别很大. a) ...
- asp.net中virtual和abstract的区别
这篇文章主要介绍了asp.net中virtual和abstract的区别,较为详细的分析了virtual与abstract的概念与具体用法,并以实例的形式予以总结归纳,需要的朋友可以参考下 本文实例分 ...
- asp.net中virtual和abstract的区别分析
这篇文章主要介绍了asp.net中virtual和abstract的区别,较为详细的分析了virtual与abstract的概念与具体用法,并以实例的形式予以总结归纳,需要的朋友可以参考下 本文实例分 ...
- C#中virtual和abstract的区别
先说区别: virtual意思是虚拟,abstract意思是抽象. virtual只修饰方法,abstract修饰方法和类. virtual方法必须有实现,abstract方法必须没有实现. publ ...
- 【C++】C++中基类的析构函数为什么要用virtual虚析构函数?
正面回答: 当基类的析构函数不是虚函数,并且基类指针指向一个派生类对象,然后通过基类指针来删除这个派生类对象时,如果基类的析构函数不是虚析构函数,那么派生类的析构函数就不会被调用,从而产生内存泄漏 # ...
- c++ virtual 和 pure virtual的区别
参考资料: http://stackoverflow.com/questions/1306778/c-virtual-pure-virtual-explained 验证代码: #include < ...
- 析构函数和Dispose的使用区别
老生常谈的问题了,MSDN也有非常详细的说明但看起来不是很系统.也曾经做过分析,但没有总结下来又忘了,这次整理一下MSDN和网上搜集的一些资料,以备不时只需. 下面是MSDN对这两个函数的建议使用方法 ...
- IO多路复用,同步,异步,阻塞和非阻塞 区别
一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...
随机推荐
- javascript中的scrollTop
含义:滚动条高度 作用:滚动加载(ajax),滚动导航固定定位,滚动弹框定位等等. 展示滚动导航和侧边栏滚动固定定位的效果:查看效果 1.chrome浏览器 document.body.scrollT ...
- angularJs
学了差不多一个礼拜,感觉这个库还是很不错的,在应用中一些小笔记,其实这些笔记现在来看确实很基础,但是把这个博客当成我自己的一个记录历程,所以我也把这点笔记拿上来: 1.是一个js框架,是一个以js语言 ...
- 实现UITextView的placeholder
我们知道在iOS开发时,控件UITextField有个placeholder属性,UITextField和UITextView使用方法基本类似,有两个小区别:1.UITextField单行输入,而UI ...
- SharePoint 2013 图文开发系列之可视化WebPart
有了WebPart开发的基础,再进行可视化WebPart开发,就容易多了.创建和开发过程,两者非常相似,下面,我们简单介绍下可视化WebPart的开发. 1.添加新项目,选择SharePoint 20 ...
- Intent属性详解二 Action、Category
先看效果图: 1.Action:该activity可以执行的动作 该标识用来说明这个activity可以执行哪些动作,所以当隐式intent传递过来action时,如果跟这里<intent-fi ...
- Activity详解二 activity数据传递
首先看效果图: 1.Bundle类的作用 Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值.相对于Map,它提供了各种常用类型的putXxx()/getXxx()方 ...
- 支付宝alipay使用小结 调用支付宝程序被杀死说明
一. 准备阶段 如果没有蚂蚁金服开放平台的注册账号,则需要实现注册一个,这里多说一点,就是当我们以公司名义注册账号时,需要预备公司的营业执照等物品(需要上传照片等信息审核).账号申请成功之后,我们需要 ...
- IOS开发之Bug--遇到一个类型不确定的bug
下面的问题不大,是我在开发中遇到的问题: 然后我就google搜一下这个报错 . 下面就解决了:
- Linq专题之提高编码效率—— 第二篇 神一样的匿名类型
说起匿名类型,我们都知道这玩意都是为linq而生,而且匿名类型给我们带来的便利性大家在实战中应该都体会到了,特别适合于一次性使用,临时 使用这些场景,虽然说是匿名类型,也就是说是有类型的,只是匿名了而 ...
- liunx作业一
一.linux发行版 linux发行版是以linux为内核,包含了系统软件和应用软件.简化系统安装的工具.软件安装升级的集成管理器. 典型的linux发行版包括:linux内核,一些GNU程序库和工具 ...