c++多态(3) -- 虚析构函数

代码:  

enum class _ANIMALS_TYPE {
	CAT,
	DOG,
	ANIMAL_COUNT
};

class Animal {
public:
	Animal(_ANIMALS_TYPE  type, int age,const char* name);
	~Animal();
	virtual void eat()const = 0;
private:
	_ANIMALS_TYPE  type;   // 动物类型
	int age;               // 动物年龄
	char* name = NULL;
};

class CAT : public Animal {
public:
	CAT(_ANIMALS_TYPE  type, int age, const char* name,const char* love);
	~CAT();
	void eat()const override;
private:
	char* love = NULL;
};

int main(void) {
	Animal* f = new CAT(_ANIMALS_TYPE::CAT, 5, "小猫", "小美");
	delete f;

	system("pause");

	return 0;
}

Animal::Animal(_ANIMALS_TYPE type, int age, const char* name)
{
	this->type = type;
	this->age = age;

	if (this->name) {
		delete this->name;
	}

	int len = strlen(name) + 1;

	this->name = new char[len];
	strncpy(this->name, name, len);
}

Animal::~Animal()
{
	cout << "调用Animal类的析构函数" << endl;

	// 如果name非空释放内存
	if (name) {
		delete name;
	}
}

CAT::CAT(_ANIMALS_TYPE type, int age,const char*name,const char*love):Animal(type,age,name)
{
	if (this->love) {
		delete this->love;
	}

	int len = strlen(love) + 1;
	this->love = new char[len];
	strncpy(this->love, love, len);
}

CAT::~CAT()
{
	cout << "调用CAT类的析构函数" << endl;
	if (love) {
		delete love;
	}
}

void CAT::eat() const
{
	cout << "猫猫吃猫粮" << endl;
}

代码分析:   

1.    我们之前讲过,如果类内部有开辟空间,那么就需要在析构函数中释放空间,上面就是这种情况,我们在父类和子类中都开辟了内存,并且在析构函数中释放了内存。

2.   我们使用多态的原则(使用父类的指针指向子类的对象),代码中我们使用new开辟了一片子类内存,然后使用父类指针指向了子类的这片内存。 

3.  当开辟子类的内存时,会调用子类和父类的构造函数,那么就会给name和love属性开辟空间。 

4.  我们给父类指针开辟空间之后,使用结束就要释放这个指针。 因为在类中有开辟空间,释放是就需要调用析构函数,将申请的内存释放掉。 

 

5.  因为我们在申请内存的时候,父类的name和子类的love都开辟了内存,按理来说释放的时候都应该释放带哦,但是如图,释放时,只调用了父类的析构函数,也就是只释放了name。 

这种情况,明显有问题,子类申请的内存不释放,就会造成内存泄露的风险。 

原因: 

其实和之前的原因类似,就是虽然我们使用父类的指针指向了子类,但是指针是父类的,在释放内存的时候自然只会调用父类的析构函数。 

解决方法: 

和之前的解决方式一样,就是在父类析构函数前加上virtual,实现虚析构函数。至于为什么,那就和之前的虚函数是类似的了。 

 加上之后: 

  

这样在父类指针指向子类内存的时候,释放父类指针,不仅会调用父类的析构函数,也会调用子类的析构函数。 

代码技巧: 

为了防止上面的情况出现,我们建议如果一个类又子类就将析构函数加上virtual,如果有上面的情况,自然不会出问题,如果没有,加上也不影响。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【蓝桥杯冲冲冲】Invasion of the Milkweed G

【蓝桥杯冲冲冲】Invasion of the Milkweed G 蓝桥杯备赛 | 洛谷做题打卡day30 文章目录 蓝桥杯备赛 | 洛谷做题打卡day30[USACO09OCT] Invasion of the Milkweed G题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题解代码我的一些话 [USACO09OCT] Invasion of the Mi…

AD域国产替代方案,助力某金融企业麒麟信创电脑实现“真替真用”

近期收到不少企业客户反馈采购的信创PC电脑用不起来&#xff0c;影响信创改造的进度。例如&#xff0c;某金融企业积极响应国产化信创替代战略&#xff0c;购置了一批麒麟操作系统电脑。分发使用中发现了如下问题&#xff1a; • 当前麒麟操作系统电脑无法做到统一身份认证&…

学生管理系统(javaSE第一阶段项目)

JavaSE第一阶段项目_学生管理系统 1.项目介绍 此项目是JavaSE第一阶段的项目,主要完成学生对象在数组中的增删改查,大家可以在此项目中发挥自己的想象力做完善,添加其他功能等操作,但是重点仍然是咱们前9个模块的知识点2.项目展示 2.1.添加功能 2.2.查看功能 2.3.修改功能 2…

DevOps落地笔记-21|业务价值:软件发布的最终目的

上一课时介绍如何度量软件的内部质量和外部质量。在外部质量中&#xff0c;我们提到用户满意度是衡量软件外部质量的关键因素。“敏捷宣言”的第一条原则规定&#xff1a;“我们最重要的目标&#xff0c;是通过持续不断的及早交付有价值的软件使用户满意”。从这一点也可以看出…

蓝桥杯Web应用开发-CSS3 新特性【练习二:获得焦点验证】

页面上有一个姓名输入框和一个密码输入框&#xff0c;当聚焦输入框时&#xff0c;输入框的背景颜色会发生改变&#xff0c; 新建一个 index3.html 文件&#xff0c;在其中写入以下内容。 <!DOCTYPE html> <html lang"en"><head><meta charset&…

mac电脑安装cocoapods出错,以及安装最新版本ruby方法

macbook安装cocoapods时碰到一个报错&#xff1a;大概率是ruby的版本太低导致的 sudo gem install cocoapods ERROR: Error installing cocoapods: ERROR: Failed to build gem native extension. ... Could not create Makefile due to some reason, probably lack of neces…

yarn/npm certificate has expired

目录 报错 原因&#xff1a;HTTPS 证书验证失败 方法 a.检查网络安全软件&#xff1a;可能会拦截或修改 HTTPS 流量 b.strict-ssl:false关闭验证【临时方法】 报错 info No lockfile found. [1/4] Resolving packages... error Error: certificate has expired at TLS…

B站UP主实时信息获取展示php源码

B站UP主实时数据展示系统 - PHP源码分享 想要实时追踪你心仪的B站UP主的最新动态吗&#xff1f;现在&#xff0c;你可以轻松获取并展示B站UP主的实时数据&#xff0c;包括粉丝数、作品数、头像、播放量等关键信息。 功能亮点&#xff1a; 实时更新&#xff1a;系统通过B站AP…

【Spring】GoF 之工厂模式

一、GoF 23 设计模式简介 设计模式&#xff1a;一种可以被重复利用的解决方案 GoF&#xff08;Gang of Four&#xff09;&#xff0c;中文名——四人组 《Design Patterns: Elements of Reusable Object-Oriented Software》&#xff08;即《设计模式》一书&#xff09;&…

洛谷_P5461 赦免战俘_python写法

捋一下这道题的思路&#xff0c;理解了题目的意思之后我们知道这道题一定会用递归。 那递归的出口很简单&#xff0c;矩阵为1x1的时候就是题目所说的不能再细分下去的意思。 问题就在于递归体。 我对于递归体的理解是找到一个普适的规律&#xff0c;这个规律适用于每一次的递归…

解决CORS错误(Spring Boot)

记录一下错误&#xff0c;以博客的形式 前言 跨域&#xff08;Cross-Origin&#xff09;是指在Web开发中&#xff0c;当一个Web应用试图从一个源&#xff08;域名、协议、端口组合&#xff09;获取资源时&#xff0c;该请求的目标与当前页面的源不同。具体来说&#xff0c;当一…

Ansible command命令模块 这个模块可以直接在远程主机上执行命令,并将结果返回本主机。

目录 参数介绍练习环境配置主机清单配置无密码链接ping模块 command 命令模块也可以用来安装点东西看个路径 command 指定目录来 指定命令 参数介绍 chdir    # 在执行命令之前&#xff0c;先切换到该目录 executable # 切换shell来执行命令&#xff0c;需要使用命令的绝对…

正点原子--STM32基本定时器学习笔记(2)

目录 1. 相关寄存器介绍 1.1 控制寄存器 1(TIMx_CR1)​编辑 1.2 DMA/中断使能寄存器(TIMx_DIER) 1.3 状态寄存器(TIMx_SR) 1.4 计数器(TIMx_CNT) 1.5 预分频器(TIMx_PSC) 1.6 自动重装载寄存器(TIMx_ARR) 2. 工程建立 3. 导入tim.c文件 4. 相关HAL库函数介绍 4.1 H…

各款Excel、word在线预览工具对比分析以及onlyoffice预览Excel加载时间长的解决方案

对于onlyoffice插件预览慢的问题分析&#xff1a; 研究了一下onlyoffice&#xff0c;得出以下结论&#xff01; 对于预览慢的问题&#xff0c;原因出在文件类型上&#xff0c;文件类型为低版本xls而非新版xlsx文件&#xff0c;onlyoffice服务器会自动将该文件转换为xlsx文件再…

服务器安装Docker (ubuntu)

前几天因为工作需求&#xff0c;要在服务器上安装Docker&#xff0c;现在把这个过程记录下来 步骤 1&#xff1a;更新软件包索引 打开终端并执行以下命令来更新包索引&#xff1a; sudo apt-get update步骤 2&#xff1a;安装必要的包 安装一些允许apt通过HTTPS使用仓库的包…

VSCode python插件:找不到自定义包导致语法解析失败

众所周知&#xff0c;在python源码中&#xff0c;我们可以通过 sys.path.append("path-to-lib") 来为python解释器添加自定义包的寻找路径。 但是vscode的默认python插件可没法聪明到根据这句话去找这个包&#xff0c;这就会导致后续代码中使用了这个库的部分无法享…

【开源】SpringBoot框架开发大病保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大病保险管理2.4 大病登记管理2.5 保险审核管理 三、系统详细设计3.1 系统整体配置功能设计3.2 大病人员模块设计3.3 大病保险模块设计3.4 大病登记模块设计3.5 保险审核模块设计 四、…

学习与学习理论 - 2024教招

一 学习的概述 1 学习的概念及其内涵 &#xff08;1&#xff09;学习的概念 学习是个体在特定情境下由于练习和反复经验而产生的行为或行为潜能的比较持久的变化。 人类的学习和动物学习的本质区别 人类学习是一个积极、主动的建构过程;人类的学习是掌握社会历史经验和个体经…

Netty中解决粘包/半包

目录 什么是TCP粘包半包&#xff1f; TCP 粘包/半包发生的原因 解决粘包半包 channelRead和channelReadComplete区别 什么是TCP粘包半包&#xff1f; 假设客户端分别发送了两个数据包 D1 和 D2 给服务端&#xff0c;由于服务端一次读取到的字节数是不确定的&#xff0c;故可…

Spring Boot 笔记 002 整合mybatis做数据库读取

概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Java Objec…