为什么有了虚析构函数,就能先调用子类的析构函数?

class A {virtual ~A(){}
};class B : A {virtual ~B(){}
};A *p = new B();
delete p;

唯一差别是,每个析构函数结束时会自动(隐含地)调上父类的析构函数,而普通虚函数并不会

本质上 当类里面有定义虚函数时,编译器会给类增加一个虚函数表,里面来存放虚函数指针,这样就增加了类的存储空间

会发现,当基类的析构函数不为虚函数时,当基类对象操控派生类对象以及对象成员时,当程序结束时会发现,派生类的析构没有调用,存在潜在的内存泄漏问题。(一句话,保证delete即指针时,正确运行析构函数)

1.首先说一下,析构顺序

派生类–> 成员类 --> 基类

2.为什么需要把基类设置为虚析构

因为多态
​ 在c++中,可以使用父类指针指向子类,产生多态行为
代码

#include <iostream>
class TestFather{
public:~TestFather() {std::cout << "~TestFather()" << std::endl;}
};
class TestChild : public TestFather {
public:~TestChild() {std::cout << "~TestChild()" << std::endl;}
};int main() {TestFather* p = new TestChild();delete p;
}//
执行结果
~TestFather()

原因就是,你直接给编译器一个TestFather指针,delete的时候,编译器一看这不就是TestFather,直接调用TestFather析构函数
换成虚析构呢
代码

#include <iostream>
class TestFather{
public:virtual ~TestFather() {std::cout << "~TestFather()" << std::endl;}
};
class TestChild : public TestFather {
public:~TestChild() {std::cout << "~TestChild()" << std::endl;}
};int main() {TestFather* p = new TestChild();delete p;
}///
执行结果
~TestChild()
~TestFather()

正确了,在delete的时候,编译器会先看TestFather的析构函数是不是虚函数,如果是的话才会产生正常的析构顺序行为派生类–>成员类–>基类

3. 虚析构函数的本质

虚析构其实也就是虚函数加上析构函数,本质就是会维护一个虚表和指向虚表的指针,在上面代码中TestFather这里面的虚表就只有~TestFather()这一个函数,使用虚函数代表会增加一个指针的内存开销

4. 默认的析构函数

当我们不定义虚构函数的时候,编译器会默认生成一个什么都不做的析构函数,但是注意了默认生成的析构函数就是普通函数不是虚函数!!!因为虚函数会带来额外开销,c++追求的是速度

5. 纯虚构析构函数

就是纯虚函数加上析构函数,一般我们把函数设置纯虚函数都是不想这个类实例化抽象出来的顶层父类,并且这个纯虚函数不能实现。但是在纯虚析构这里不同
代码

#include <iostream>
class TestFather{
public:virtual ~TestFather() = 0;
};
TestFather::~TestFather() {std::cout << "~TestFather()" << std::endl;
}class TestChild : public TestFather {
public:~TestChild() {std::cout << "~TestChild()" << std::endl;}
};int main() {TestFather* p = new TestChild();delete p;
}//结果和上面的相同

6. 总结:

明确你的类会不会被继承,当作基类使用,把类的析构函数都设置为虚函数和不设置为虚函数都是不好的
​ 1.如果你的类会被继承,当作基类,那么一定要把基类析构函数设置为虚函数
​ 2.如果你的类不会被继承,单纯的类,那么不需要把析构函数设置为析构函数,因为会浪费空间,多一个虚表指针

【C++】浅析析构函数(基类中)为什么要写成虚基类?相关推荐

  1. php dump utfp,php pchart乱码-使用REST接口获取GeoServer中的...-结合 thinkPHP 分页写成自己分页类_169IT.COM...

    本页文章导读: ▪php pchart乱码      有俩种情况:①:未将中文字符编码格式修改成utf-8 (例子如下:)mb_convert_encoding($data, "html-e ...

  2. 编写Java程序,使用ThreadLocal类,项目中创建账户类 Account,类中包括账户名称name、 ThreadLocal 类的引用变量amount,表示存款

    查看本章节 查看作业目录 需求说明: 某用户共有两张银行卡,账户名称相同,但卡号和余额不同.模拟用户使用这两张银行卡进行消费的过程,并打印出消费明细 实现思路: 项目中创建账户类 Account,类中 ...

  3. java有且仅有一个main_组成java Application的若干类中,有且仅有一个主类,只有主类中含有主方法main();...

    [单选题]Java 应用程序入口的 main 方法,其声明格式可以是(A) [填空题]点的水平投影与正面投影的连线( ) 于 OX 轴. [单选题]-Is there anything wrong w ...

  4. 声明银行账户类 java_编写Java程序,使用ThreadLocal类,项目中创建账户类 Account,类中包括账户名称name、 ThreadLocal 类的引用变量amount,表示存款...

    查看本章节 查看作业目录 需求说明: 某用户共有两张银行卡,账户名称相同,但卡号和余额不同.模拟用户使用这两张银行卡进行消费的过程,并打印出消费明细 实现思路: 项目中创建账户类 Account,类中 ...

  5. 析构函数为什么写成虚函数?

    由于类的多态性,基类指针可以指向派生类的对象.如果删除该基类的指针,就会调用该指针指向的派生类的析构函数,而派生类的析构函数又会自动调用基类的析构函数,这样整个派生类的对象被完全释放.· 如果析构函数 ...

  6. 【Java 虚拟机原理】Java 类中的类加载初始化细节 ( 只使用类中的常量时加载类不会执行到 ‘初始化‘ 阶段 )

    文章目录 一.类加载初始化时机 二.常量加载示例 三.数组加载示例 一.类加载初始化时机 类加载时机 : Java 程序执行时 , 并不是一开始将所有的字节码文件都加载到内存中 , 而是用到时才进行加 ...

  7. 复制类中的属性值到另一个类的相同属性中

    代码有好多高级代码,现在给大家看一个,就是复制相同属性的值到另一个类. 例如:A类中有String name,int score:B类中有String name ,int score,String s ...

  8. 构造函数为什么一般不定义为虚函数?而析构函数一般写成虚函数的原因 ?

    1.构造函数不能声明为虚函数 1)因为创建一个对象时需要确定对象的类型,而虚函数是在运行时确定其类型的.而在构造一个对象时,由于对象还未创建成功,编译器无法知道对象的实际类型,是类本身还是类的派生类等 ...

  9. java类使用其他类的变量_如何将java类中的变量加载到其他类

    我之前已经在类之间加载了变量,但现在无法使它工作 . 首先,我有我的代码,我尝试加载它 . 包XMLTest; public class ModifyTTXML { public static voi ...

最新文章

  1. C 语言编程 — size_t 的意义与作用
  2. 堆和栈组合:双端队列c++
  3. python搜题软件-智慧职教mooc的APPPython程序设计基础章节测验答案
  4. 学python比较好的书-学习Python编程的最好的几本书
  5. Python进阶11-标准库介绍02
  6. opencv4.4.0函数手册_Cobalt strike3.0使用手册
  7. oracle 匿名段,这段匿名块看着没什么问题啊
  8. 免费体验,阿里云智能LOGO帮你解决设计难题
  9. python中的字典和类的区别_Python:我应该使用类还是字典?
  10. 流畅的python 数据模型
  11. Docker的主要作用
  12. linux随手笔记(Centos为主)
  13. JS高级程序设计精简版(第十章:函数)附思维导图
  14. VIPKID前端面试题
  15. 惊喜盲盒中奖iPhone 13已收到货
  16. PHP中级工程师面试题
  17. opencv 视频处理(python)
  18. 大批,程序员被劝退!
  19. TCP报文格式及三次握手详解
  20. Manifest merger failed with multiple errors, see logs问题处理

热门文章

  1. c语言求跳水运动员成绩,跳水排名_C语言编程实例_C语言_最全面的网站教程
  2. 量子计算机真随机数,量子真随机数发生器研究取得进展
  3. linux 多目录makefile,royalchen
  4. android百度api配置,Android Studio 配置使用百度api (附带简单样例)(示例代码)
  5. C/C++数组初始化的一些误区
  6. 前端如何查看音频的长度_重学前端基础:如何查看文档对象的所有属性?如何文档查找节点?...
  7. Debevec方法计算相机响应函数CRF
  8. 剑指offer:面试题24. 反转链表
  9. C++中结构体与类的区别(struct与class的区别)
  10. 机器学习与高维信息检索 - Note 7 - 核主成分分析(Kernel Principal Component Analysis,K-PCA)