//program 15.5.1.Cpp
#include < iostream >
#define TO_VERSION_NEW 1/*根据需要是否将(基类)虚构函数编译为虚析构函数(virtual版)*/
using namespace std;
class CShape
{public:#if TO_VERSION_NEWvirtual ~CShape()
#else~CShape()
#endif{cout << "CShape: :destrutor" << endl;};
};
class CRectangle : public CShape
{public:int W, h;    //宽和高/*如果基类的析构函数是虚函数,派生类的析构函数也自动会变成虚函数(如果没有特地加virtual的话)*/~CRectangle() { cout << "CRectangle:: destrutor" << endl; }
};
int main()
{CShape* p = new CRectangle;/*派生类对象的内存地址赋值给基类指针,如果析构函数不是虚函数,那么p所指的内存被释放掉后,编译器只知道p的(定义时)的类型是基类型CShape,调用的析构函数也到CShape中去找(因为编译器不知道p所指的那个对象那个对象是基类型本身的对象还是基类型所派生的类型的对象.)*/delete p;/*如果没有delete就不会触发任何析构函数.*/return 0;
}
/*程序的输出结果:
非虚析构函数版本的输出CShape::destrutor
*//*输出的结果说明执行“delete p;" 只引发了CShape 类的析构函数被调用,没有引发CRectangle类的析构函数调用。
这是因为该语句是静态联编的,编译器编译到此时,不可能知道此时p到底指向那个类型的对象,
它只根据 p的类型 是CShape*,来决定应该调用CShape类的析构函数。
但按理说,“delete p;”导致一个CRectangle类的对象消亡,应该调
用CRectangle类的析构函数才符合逻辑,否则有可能引发程序的bug。例如,假设程序需要对CRetangle对象进行计数,那么此处不调用CRetangle类的析构函数,就会导致计数不正确(如果借助析构函数来计数)。
再如,假设CRectangle对象存续期间进行了动态内存分配,而释放内存的操作都是在析构函数中进行的,那么此处不调用CRetangle类的析构函数,就会导致被delete的对象中的动态分配的内存以后再也没有机会回收。
综上所述,希望“delete p;”这样的语句,能够聪明地根据p所指向的对象,来执行相应的析构函数。实际上,这也是多态。
为了在这种情况下实现多态,C++规定,需要将基类的析构函数声明为虚函数,即虚析构函数。将上面的程序中的CShape类改写,在析构函数前加“virtual"关键字,将其声明为虚函数:
class CShape
{
public:
virtual ~ CShape() { cout << " CShape: destrutor"<< endl; }
};
则程序的输出结果变成:
CRectangle:: destrutor
CShape :: destrutor
说明CRetangle类的析构函数被调用了。
实际上,派生类的析构函数,会自动调用基类的析构函数(是自下而上的)。而且,
只要基类的析构函数是虛函数,那么派生类的析构函数不论是否用“virtual"关键字声明,都自动成为虚析构函数。(不同类的析构函数名显然不同,其实这里不需要同名同参数)一般来说,一个类如果定义了虛函数,
则最好将析构函数也定义成虚函数。(使得
*//*版本_2*/

C++虚析构函数实例相关推荐

  1. C++继承中构造函数、析构函数调用顺序及虚析构函数

    首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就可以调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  2. unique函数_C++智能指针2:(虚?)析构函数(标准与实现的差异)

    只要是有良心的 C++ 教材,总是会苦心孤诣地告诫初学者,在继承关系中,应该把父类的析构函数定义成虚函数.这已然成为一条铁律,如果违背,不仅有内存泄漏的风险,在多继承情况下甚至会出现未定义行为.因此, ...

  3. C++ 虚析构函数

    类型需要虚析构函数的另外一个特征 是该类型具有指针成员或引用成员.如果有指针成员和引用成员,则该类型通常需要实现析构函数以及拷贝操作. 通常,一个实现了析构函数的类型同时也需要实现拷贝构造函数与拷贝复 ...

  4. C++继承中析构函数 构造函数的调用顺序以及虚析构函数

    首先说说构造函数.大家都知道构造函数里就能够调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就能够调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  5. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?...

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

  6. c++ map 析构函数_C++|类继承关系中的虚函数、虚析构函数、虚基类

    在继承关系中,虚函数.虚析构函数.虚基类中使用的关键字virtual都是在告诉编译器,此处要进行特殊处理: 虚函数:函数重写时的要求编译器动态绑定来实现多多态 : 虚析构函数:当基类指针指向在堆内实现 ...

  7. C++ 虚析构函数作用

    简单的来说,虚函数的作用是当基类调用派生类的对象时,能够实现多态,即虚函数会优先调用派生类的对应函数. 那么虚析构函数的作用:就是释放派生类的内存,防止内存泄漏. 实例: 第一种情况,当没有虚析构函数 ...

  8. 面试中常被问到(五)C++析构函数,虚析构函数

    C++析构函数 (1)对于析构函数:析构函数与构造函数相呼应,从调用构造函数开始到自动执行析构函数二者调用期间即为所创建对象实例的生命周期. (2)析构函数与类名相同,仅前面加一个~,一般析构函数无参 ...

  9. 虚函数,虚析构函数,纯虚函数

    虚函数 虚函数:虚函数是运行时多态,若某个基类函数声明为虚函数,则其公有派生类将定义与其基类虚函数原型相同的函数.那么,当基类指针或基类引用操作派生类对象时,系统会自动用派生类中的同名函数代替基类虚函 ...

最新文章

  1. 啊里大鱼短信发送API
  2. 十条nmap常用的扫描命令
  3. Java IO流及应用(一)
  4. 模拟springIOC容器的annotation
  5. android保存文件到手机内存
  6. r.java是什么_R.java文件介绍
  7. Hadoop学习笔记
  8. CLR 4.0 有哪些新东西? What's new in CLR 4.0--类型嵌入 Type embedding
  9. 【个人笔记】OpenCV4 C++ 图像处理与视频分析 04课
  10. oracle 11g sql和pl/sql从入门到精通,Oracle 11g SQL和PL SQL从入门到精通_IT教程网
  11. H.266代码学习:xCheckRDCostMerge2Nx2N函数
  12. cmd imp导入dmp文件_oracle导入dmp文件的2种方法
  13. Java实现图片水印
  14. SAR、PAR和DAR
  15. 电脑桌面图标点击没反应
  16. pygame实现打飞机小游戏
  17. Defcon - 2015 - 初赛 - r0pbaby writeup
  18. 基于MatlabSimulin的微电网模型及光伏电池建模仿真分析
  19. 全息投影的三种热门展示方式
  20. 上海职称不用考计算机和英语翻译,英语翻译专业资格考试替代职称评定

热门文章

  1. 从高德地图大批量扒取数据,并写入excel
  2. 西湖晨练偶记:移动互联网的未来
  3. 反驳:程序员不是吃青春饭的—只有码农是,编程能力与年龄无关
  4. python用户界面导入图片_python图形用户界面(六):可视化给图片添加上文字
  5. python selenium对象怎么序列化_Python Selenium如何操作Cookies
  6. js sort排序 filter过滤
  7. 手牵手教Docker部署Springboot+vue ,全过程十分详细,轻松完成项目部署(简单,高效,通用)
  8. word2vec 介绍
  9. 基于simulink的通信系统设计学习总结
  10. matlab中trapz的用,matlab使用trapz函数对积分的运算