【Effective C++】条款7:为多态基类声明virtual析构函数

news2025/1/24 10:58:58

如果你实现的一个类打算作为基类,并且要实现多态,那么就应该将析构函数声明为virtual。

class TimeKeeper
{
public:
	TimeKeeper();
	~TimeKeeper();
};
TimeKeeper::TimeKeeper()
{
	cout << "TimeKeeper构造" << endl;
}
TimeKeeper::~TimeKeeper()
{
	cout << "TimeKeeper析构" << endl;
}

class AtomicClock : public TimeKeeper
{
public:
	AtomicClock();
	~AtomicClock();
};
AtomicClock::AtomicClock()
{
	cout << "AtomicClock构造" << endl;
}
AtomicClock::~AtomicClock()
{
	cout << "AtomicClock析构" << endl;
}


int main()
{
	TimeKeeper* ptr = new AtomicClock;
	delete ptr;
	return 0;
}

可见,父类指针指向子类对象时,当用该指针去调用析构函数,实际上调用的是父类的析构函数,这会导致子类中自己的那部分资源没有得到处理。

解决方案:将父类的析构函数声明为virtual 

virtual ~TimeKeeper();

简单说一下原理:

如果一个类有成员函数是虚函数,那么编译器将会为该类生成一张虚表,存放该类的虚函数地址。

实例化的对象中会额外增加一个虚表指针vptr,该指针指向虚表。

当用父类指针调用虚函数时,从指向的对象中拿到虚表指针,到虚表中找到该类的虚析构函数,再去调用。

你只需记住:任何具有虚函数的类都应有虚析构函数。因为虚函数就是为了实现多态,多态就可能出现上面的情况。

提示一下,多态基类的析构函数要加virtual,子类可加可不加,因为不管你加不加,它都是virtual的。

当一个类不打算成为多态基类时,就不应将析构函数设为虚函数。

原因很简单,因为有虚函数的类实例出的对象中,会额外增加一个指针浪费空间。

STL中的很多类都没有虚析构函数,不要随意继承它们,否则容易出问题

 如果你想要一个抽象类(不能实例化对象),但没有任何纯虚函数时,可以声明一个纯虚析构函数。但是,你必须为该析构函数提供定义。

class AWOV
{
public:
	virtual ~AWOV() = 0;
};
AWOV::~AWOV()
{}

 

纯虚函数的目的就是要求它的子孙类都提供这样一个接口,是为了实现规范,而不是用来调用的,所以一般不用给出定义。但纯虚析构函数必须给出定义,因为子类对象析构时会调用父类的析构函数,如果不提供定义会链接错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1297779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修改移远提供的GobiNet、quectel-CM源码,使其支持有方N720 4G模块

最近在研究imx6ull linux下4G模块驱动的移植&#xff0c;参考的移远ec20的移植方法&#xff0c;添加了GobiNet驱动&#xff0c;编译了quectel-CM工具&#xff0c;并且可以正常拨号&#xff0c;分配到ip&#xff0c;如下&#xff1a; ping外网也没有压力&#xff0c;如下…

MySQL之数据库及表操作

MySQL之数据库及表操作 文章目录 MySQL之数据库及表操作一、数据库的基本结构二、数据库的创建和删除三、数据表的结构定义和操作四、数据的插入五、主键和自增长属性1、什么是主键2、自增长属性 一、数据库的基本结构 数据库系统由数据库服务器为载体&#xff0c;拥有一个或者…

实用篇 | 一文学会人工智能中API的Flask编写(内含模板)

----------------------- &#x1f388;API 相关直达 &#x1f388;-------------------------- &#x1f680;Gradio: 实用篇 | 关于Gradio快速构建人工智能模型实现界面&#xff0c;你想知道的都在这里-CSDN博客 &#x1f680;Streamlit :实用篇 | 一文快速构建人工智能前端展…

class063 双向广搜【算法】

class063 双向广搜【算法】 算法讲解063【必备】双向广搜 code1 127. 单词接龙 // 单词接龙 // 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 // 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk &#xff1a; // 每一对相邻的单词只…

听GPT 讲Rust源代码--src/tools(10)

File: rust/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs 在Rust源代码中&#xff0c;rust-analyzer是一个Rust语言的IDE插件和代码分析器。其中&#xff0c;generate_is_empty_from_len.rs是rust-analyzer中的一个处理程序&#x…

超声波清洗机可以清洗什么?2023年超声波清洗机推荐

之前跟朋友聊天了解到&#xff0c;他作为一个眼镜党&#xff0c;竟然不知道要清洗自己的眼镜&#xff0c;如果眼镜长时间不清洗的话&#xff0c;很容易细菌感染并且导致眼睛酸痛&#xff0c;这是一个弊端&#xff0c;还有就是如果不正确清洗眼镜方法也很容易导致眼镜被刮花&…

算数运算符和算数表达式

基本算数运算符 算数运算符&#xff1a; &#xff08;加法运算符或正值运算符&#xff09;、-&#xff08;减法运算符或负值运算符&#xff09;、*&#xff08;乘&#xff09;、/&#xff08;除&#xff09;、%&#xff08;求余数&#xff09; 双目运算符&#xff1a; 双目…

行业地位失守,业绩持续失速,科沃斯的故事不好讲

特劳特曾在《定位》一书中提到&#xff0c;为了在容量有限的消费者心智中占据品类&#xff0c;品牌最好的差异化就是成为第一&#xff0c;做品类领导者或开创者&#xff0c;销量遥遥领先&#xff1b;其次分化品类&#xff0c;做到细分品类的唯一&#xff0c;即细分品类的第一。…

C# Solidworks二次开发:三种获取SW设计结构树的方法-第三讲

今天要讲的文章接着上一篇讲&#xff0c;第三种获取SW设计结构树的方法。 这个方法的逻辑是通过先获取第一个特征&#xff0c;然后通过循环不断的寻找下一个特征来完成获取所有节点。 1、获取第一个特征的API如下所示&#xff1a;FirstFeature Method (IModelDoc2) 这个API的…

构建Servlet项目流程

第一步&#xff1a;创建maven项目 部分基础 依赖的模板基础部分如下 maven-archetype-quickstart: 这是最基本的Archetype&#xff0c;它创建一个包含简单Java类和单元测试的项目。 maven-archetype-webapp: 这个Archetype创建一个简单的Java web应用&#xff0c;包括一个serv…

(数据结构)单链表的定义

#include<stdio.h> typedef struct LNode {int data;struct LNode* next; }LNode,*LinkList; //LNode为结构体类型&#xff0c;LinkList为指向单链表的指针 //初始化一个空的单链表 void InitList(LinkList L) {L NULL; //空表&#xff0c;暂时没有任何节点 } //判断单…

启动游戏出现concrt140.dll错误的8种解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是找不到concrt140.dll文件。这个错误通常会导致程序无法正常运行&#xff0c;给用户带来困扰。本文将介绍找不到concrt140.dll无法继续执行代码的8个方法&#xff0c;同时探讨concrt140.dll丢…

六:Day03_Mybatis-Plus

一、介绍 MyBatis-Plus&#xff08;简称 MP&#xff0c;是由baomidou(苞米豆)组织开源的&#xff09;是一个基于 MyBatis 的增强工具&#xff0c;它对 Mybatis 的基础功能进行了增强&#xff0c;但未做任何改变&#xff0c;Mybatis-Plus 其实可以看作是对 Mybatis 的再一次封装…

Compilation failureFailure executing javac, but could not parse the error

记一次maven编译错误导致的打包失败问题。错误如下 Compilation failure Failure executing javac, but could not parse the error: javac: Ч ı :  ? : javac <options> <source files> -help г ܵ ѡ 排查路径如下&#xff1a; 1&#xff…

java+springboot+ssm学生社团管理系统76c2e

本系统包括前台和后台两个部分。前台主要是展示社团列表、社团风采、社团活动、新闻列表等&#xff0c;前台登录后进入个人中心&#xff0c;在个人中心能申请加入社团、查看参加的社团活动等&#xff1b;后台为管理员与社团负责人使用&#xff0c;应用于对社团的管理及内容发布…

C#之扩展方法详解

前言&#xff1a; 我们想要向一个类型中添加方法&#xff0c;可以通过以下两种方式&#xff1a; 1.修改源代码。 2.在派生类中定义新的方法。 但是这两种方式都有缺点&#xff0c;1如果是别人的代码&#xff0c;你对其直接进行修改&#xff0c;可能破坏代码的完整性&#x…

高项备考葵花宝典-项目进度管理输入、输出、工具和技术(下,很详细考试必过)

项目进度管理的目标是使项目按时完成。有效的进度管理是项目管理成功的关键之一&#xff0c;进度问题在项目生命周期内引起的冲突最多。 小型项目中&#xff0c;定义活动、排列活动顺序、估算活动持续时间及制定进度模型形成进度计划等过程的联系非常密切&#xff0c;可以视为一…

【MySQL】MySQL的varchar字段最大长度是65535?

在MySQL建表sql里,我们经常会有定义字符串类型的需求。 CREATE TABLE `user` ( `name` varchar(100) NOT NULL DEFAULT COMMENT 名字) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ; 比方说user表里的名字,就是个字符串。MySQL里有两个类型比较适合这个场景。 char和varchar。…

Nexus搭建npm私库(角色管理、上传脚本)

安装Nexus 官网下载 https://www.sonatype.com/products/sonatype-nexus-oss-download 进入官网下载&#xff0c;最新下载方式需要输入个人信息才能下载了 选择对应的系统进行下载 Windows 推荐也下载 UNIX 版本&#xff08;Windows 版本配置比较难改&#xff09; 如果没有下…

TrustZone之SMC异常

作为支持两个安全状态的一部分&#xff0c;该架构包括了Secure Monitor Call&#xff08;SMC&#xff09;指令。执行SMC会引发Secure Monitor Call异常&#xff0c;该异常目标是EL3。 通常&#xff0c;SMC用于请求服务&#xff0c;可以是来自驻留在EL3中的固件&#xff0c;也可…