1.第一段代码

#include<iostream>
using namespace std;
class ClxBase{
public:ClxBase() {};~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};class ClxDerived : public ClxBase{
public:ClxDerived() {};~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int   main(){ClxDerived *p = new ClxDerived;p->DoSomething();delete p;return 0;
}

  

运行结果:

Do something in class ClxDerived!

Output from the destructor of class ClxDerived!

Output from the destructor of class ClxBase!

这段代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源.

2.第二段代码

#include<iostream>
using namespace std;
class ClxBase{
public:ClxBase() {};~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};class ClxDerived : public ClxBase{
public:ClxDerived() {};~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }
};
int   main(){ClxBase *p = new ClxDerived;p->DoSomething();delete p;return 0;
}

  

输出结果:

Do something in class ClxBase!
Output from the destructor of class ClxBase!

这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用dosomething()函数执行的也是基类定义的函数.

一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.

在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.

析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.

3.第三段代码:

#include<iostream>
using namespace std;
class ClxBase{
public:ClxBase() {};virtual ~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; };virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};class ClxDerived : public ClxBase{
public:ClxDerived() {};~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};int   main(){ClxBase *p = new ClxDerived;p->DoSomething();delete p;return 0;
}

  

运行结果:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!

这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数.

如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.

转载于:https://www.cnblogs.com/zhangj95/p/4518232.html

为什么基类的析构函数是虚函数?相关推荐

  1. 虚函数、纯虚函数、虚基类、抽象类、虚函数继承、虚继承

    虚函数:虚函数是C++中用于实现多态(polymorphism)的机制.核心理念就是通过基类访问派生类定义的函数.是C++中多态性的一个重要体现,利用基类指针访问派生类中的成员             ...

  2. C++的虚基类,抽象类,虚函数,纯虚函数,virtual

    虚基类 在说明其作用前先看一段代码 class A { public: int iValue; }; class B:public A { public: void bPrintf(){cout< ...

  3. 声明一个哺乳动物类Mammal,再由此派生出狗类Dog,二者都定义Speak()成员函数,基类中定义为虚函数,声明类Dog的一个对象,调用函数Speak()

    #include <iostream.h> #include <string.h> class Mammal { protected:  char name[10]; publ ...

  4. 为什么基类的析构函数要声明成虚函数

    记得以后基类(父类) 的析构函数最好是声明为 虚函数 即:virtual 开发中遇到了一个比较傻逼的bug,也证明了理论与实际之间的差距. 在基类中没有声明其析构函数为虚函数,导致delete 释放操 ...

  5. C++通过基类指针delete派生类数组,析构函数是虚函数,程序为什么会崩溃? https://www.zhihu.com/question/30838092/answer/49623765

    https://www.zhihu.com/question/30838092/answer/49623765 C++通过基类指针delete派生类数组,析构函数是虚函数,程序为什么会崩溃? 代码如下 ...

  6. 析构函数声明无效_C++基类的析构函数为何要声明为虚函数

    C++的类中,构造函数用于初始化对象及相关操作,构造函数是不能声明为虚函数的,因为在执行构造函数前对象尚未完成创建,虚函数表还不存在. 析构函数用于销毁对象完成时相应资源的释放工作,析构函数可以被声明 ...

  7. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  8. 类5-类的继承、虚函数、纯虚函数、虚析构函数

    一.类的继承 就像家谱一样,就是一个继承图.爷爷-父亲-儿子-孙子等.类也一样,上面的类称为基类,也称父类.基类下面的类叫子类也叫派生类. 子类对父类的一些属性等有所继承也有所发展,因此才有了类的继承 ...

  9. unique函数_C++核心准则C.35:基类的析构函数必须满足的条件

    C.35: A base class destructor should be either public and virtual, or protected and nonvirtual 基类的析构 ...

最新文章

  1. 强哥PS强化培训班课程目录
  2. 【国内首家】第一个基于语音生成实时知识图谱的系统来啦!!!
  3. java,关键字static
  4. [html] html的img标签为什么要添加alt属性呢?
  5. 蓝桥杯入门训练序列求和
  6. 试验IFTTT同步发微博
  7. CentOS7搭建FTP文件服务器
  8. 服务评价器连接计算机后无法启动,win10专业版远程桌面Remote Desktop Connection已停止工作?...
  9. CSDN博客下载器v2.0发布(导出PDF)
  10. 基于单片机的无线病房呼叫系统设计
  11. 目前流行的操作系统有哪些
  12. Thinkphp 5.0 仿百度糯米开发多商家电商平台
  13. 面试突击63:distinct 和 group by有什么区别?
  14. 《被讨厌的勇气》书摘心得之一切烦恼都来自人际关系(2)
  15. 惠普HP Laser MFP 136a 打印机驱动
  16. execute immediate在存储过程中的使用
  17. 幼师计算机word,幼儿园大班老师教养笔记范文
  18. excel 查询 表关联_从Excel查询表获取里程
  19. 告诉你那里最受欢迎,python爬取全国13个城市旅游数据
  20. python pip怎么安装包_python怎么用pip安装包

热门文章

  1. 关于出现Not an editor command: Bundle ‘**/*.vim‘的解决方案【转】
  2. IntelliJ idea 创建Web项目后web文件夹下没有WEB-INF的解决方法
  3. 解决background图片拉伸问题
  4. 标签中的onclick调用js方法传递多个参数的解决方案
  5. 带参数的RedirectToAction
  6. 如何检查正在运行脚本的Python版本?
  7. Spring的Bean属性依赖注入
  8. linux源代码存放在哪个目录_入门Linux,从了解Linux文件系统的目录结构开始
  9. java date eee_java将 Date原始格式EEE MMM dd HH:mm:ss Z yyyy转成指定格式
  10. 洛谷——P1720 月落乌啼算钱(斐波那契数列)