C++回顾——虚析构

news2025/1/9 1:43:06

一、示例代码

#include<iostream>
using namespace std;

class Weapon {
public:
	virtual void getWeapon() = 0;
	//virtual ~Weapon() = default;
};

class bow :public Weapon
{
public:
	void getWeapon() override
	{
		cout << "弓箭 " << ends;
	}
	~bow()
	{
		cout << "弓箭损坏了!" << endl;
	}
};

class gun :public Weapon
{
public:
	void getWeapon() override
	{
		cout << "火枪 " << ends;
	}
	~gun()
	{
		cout << "火枪损坏了!" << endl;
	}
};
void weapon_delete(Weapon* test)
{
	delete test;
}
int main(int argc,char** argv)
{
	Weapon* my_bow = new bow();
	weapon_delete(my_bow);

	Weapon* my_gun = new gun();
	weapon_delete(my_gun);
    return 0;
}

执行上面示例代码我们发现:
并未执行我们预期的析构函数
在这里插入图片描述

如果解开Weapon类中的virtual ~Weapon() = default;我们发现,符合我们的预期:
在这里插入图片描述
我们在基类中引入了虚析构,达到了我们的目标。来看看虚析构有啥用吧!

二、引入虚析构前后各类虚函数表结构

我们来观察下引入虚析构前后各类的虚函数表中的结构
参考链接:如何通过vs查看类的内存结构
引入前:
在这里插入图片描述
引入后:
在这里插入图片描述)
结论:
引入虚析构之后,我们发现派生类bow的虚函数表中,多了一个析构函数!

二、为何引入虚析构?

引入虚析构函数的主要目的是解决对象生命周期管理中的问题,尤其是在多态和继承的上下文中。下面是引入虚析构函数的几个重要原因:

1. 正确清理资源

在使用多态时,通常会通过基类指针或引用来操控派生类对象。当基类对象被删除时,如果基类的析构函数不是虚拟的,仅会调用基类的析构函数。这将导致派生类未释放的资源(如动态分配的内存、打开的文件句柄等)无法正确清理,可能引发内存泄漏或其他资源泄漏问题。

2. 保障对象完整性

虚析构函数确保在删除对象时遵循一个完整的析构顺序:先调用派生类的析构函数,再调用基类的析构函数。这种机制有助于确保对象的完整性和正确的资源管理,避免未定义行为。

3. 提高代码的可维护性

当类设计包括多态性时,正确实现虚析构函数使得代码更加模块化、可重用和可扩展。这样,通过基类指针传递的对象能够安全地在运行时处理其实际类型的析构逻辑,降低了手动管理内存和资源的复杂性。

4. 支持复杂的继承结构

在复杂的多层继承结构中,确保基类的析构函数为虚函数是很重要的。这样,任何派生类都可以正确地释放其资源,维护层次结构的完整性。

示例

以下是一个简单的示例,说明如果不使用虚析构函数,可能导致的问题:

#include <iostream>
using namespace std;

class Base {
public:
    ~Base() { cout << "Base Destructor called" << endl; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived Destructor called" << endl; }
};

void function(Base* obj) {
    delete obj; // 如果 Base 的析构函数不是虚拟的
}

int main() {
    Base* obj = new Derived();
    function(obj); 
    // 将只调用 Base 的析构函数,导致 Derived 的析构函数不会被调用
    return 0; 
}

在这个例子中,由于 Base 的析构函数不是虚拟的,即使 obj 实际上是一个 Derived 对象,Derived 的析构函数也不会被调用,从而导致资源泄漏。

总结

总的来说,虚析构函数的引入是为了确保在从基类指针删除派生类对象时能够正确调用派生类的析构函数,以便完成资源清理,维护程序的健壮性和安全性。通过这一机制,C++ 提供了一种可靠的方式来管理多态性带来的复杂性,增强了面向对象编程的灵活性和可维护性。

三、总结

虚析构作用:通过基类指针、引用 释放 子类的所有空间。

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

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

相关文章

支持对接OpenAI、Ollama和本地向量模型,MaxKB开源知识库问答系统发布v1.4.0版本

2024年8月1日&#xff0c;MaxKB开源知识库问答系统正式发布v1.4.0版本。在这一版本中&#xff0c;MaxKB的社区版支持对接OpenAI、Ollama和本地的向量模型&#xff0c;并且支持设置模型的使用权限&#xff0c;同时MaxKB还支持知识库自定义向量模型。 自v1.4.0版本开始&#xff…

坐牢第二十一天 20240801(IO)

一.作业 1、使用两个线程完成两个文件的拷贝&#xff0c;分支线程1拷贝前一半&#xff0c;分支线程2拷贝后一半&#xff0c;主线程回收两个分支线程的资源 #include <myhead.h> struct Node {char *src;char *dest;int start;int len; }; //定义求源文件大小的函数 int…

python爬虫初识

一、什么互联网 互联网&#xff08;Internet&#xff09;是全球范围内最大的计算机网络&#xff0c;它将数以百万计的私人、公共、学术、商业和政府网络通过一系列标准通信协议&#xff08;如TCP/IP&#xff09;连接起来形成的一个庞大的国际网络。 互联网的起源可以追溯到196…

【C++】1.C++入门(1)

文章目录 1.C关键字2.命名空间2.1 命名空间定义2.2 命名空间使用 3.C输入&输出4.缺省参数4.1 缺省参数概念4.2 缺省参数分类 5.函数重载5.1 函数重载概念5.2 C支持函数重载的原理--名字修饰(name Mangling) 1.C关键字 C总计63个关键字&#xff0c;C语言32个关键字 2.命名空…

0206创建场景状态的基础接口

一、创建一个类 二、写一个类&#xff0c;作为接口类的作用&#xff08;不一定是interface&#xff09;

ctfshow 大赛原题 web689--web695

web689 <?php error_reporting(0); if(isset($_GET) && !empty($_GET)){$url $_GET[file];$path "upload/".$_GET[path];}else{show_source(__FILE__);exit(); }if(strpos($path,..) > -1){ //检查 $path 是否包含 ..&#xff0c;以防止路径注…

Podman 发布 v5.2.0-RC3

这是 v5.2.0 的最终候选版本。以下是初步的发布说明。 功能 Podman 现在支持使用 libkrun 作为在 MacOS 上创建虚拟机的后端。libkrun 后端的优势在于允许将 GPU 挂载到虚拟机中以加速任务。默认后端仍然是 applehv。Quadlet 现在支持.build 文件&#xff0c;这使得可以由 Quad…

2024PDF编辑工具新趋势:从基础到高级的全方位方案

随着数字化办公的发展&#xff0c;我们对PDF编辑的需求也日益增长。从最开始对文字的修改到现在可以插入音频、视频文件。这些都离不开PDF编辑软件的功劳&#xff0c;那有什么好用的PDF编辑工具呢&#xff0c;听我娓娓道来。 1.福昕PDF编辑器 直达链接&#xff1a;https://e…

【轨物方案】分布式光伏电站运维智能化升级方案

分布式光伏电站从2010年开始在国内推广&#xff0c;到2022年底&#xff0c;全国工商业分布式光伏电站装机容量为157.62GW&#xff0c;并且新增装机量逐年递增。以1MW/电站计算&#xff0c;保守估计全国至少已有十几万个工商业分布式光伏电站。 这些电站的运维工作是往往交给专业…

百度松果菁英班作业整理(第一期)

本期的题目比较简单&#xff0c;最后两题稍微复杂&#xff0c;但是主题思路也不难&#xff0c;大家可以一起练习。 孪生质数 在质数中&#xff0c;若两个质数之差为2,我们称之为孪生质数,例如(3、5)(5、7)&#xff0c;输入2个正整数&#xff0c;判断他是不是孪生质数,输出YE…

大数据技术原理-MapReduce的应用

摘要 本实验报告详细阐述了在“大数据技术原理”课程中进行的MapReduce编程实验。实验环境基于Hadoop平台和Ubuntu操作系统。实验的核心内容包括使用MapReduce编程模型实现文件的合并去重、排序以及对给定表格信息的挖掘。实验过程中&#xff0c;我们首先在Hadoop分布式文件系…

基于统计检验与随机森林分析不同天气类型的影响因素

1.项目背景 本项目使用了一个人工合成的天气数据集&#xff0c;模拟了雨天、晴天、多云和雪天四种类型&#xff0c;在分析过程中&#xff0c;对数据进行了异常值处理&#xff0c;并通过描述性统计对数据进行了初步探索&#xff0c;接着&#xff0c;使用Kruskal-Wallis检验、Du…

Flutter连接iPad报错Developer Mode

Flutter连接iPad报错Developer Mode To use 黑色iPad for development, enable Developer Mode in Settings → Privacy & Security.根据错误提示&#xff0c;在ipad中的“安全性”中没有“开发者模型”选项。 打开安全模式步骤: 需要打开Xcode,连接iPad, 在iPad中点击“…

app逆向抓包技巧:ROOT检测绕过

本篇博客旨在记录学习过程&#xff0c;不可用于商用等其它途径 场景 某监管app查壳发现使用了 《梆梆企业版》 加固&#xff0c;想尝试使用frida-dexdump脱壳&#xff0c;打开app发现提示下图样式&#xff0c;由于进不去界面&#xff0c;我们直接脱壳无法保证能获取到完整的 …

虚拟机windows server创建域

目录 准备工作 一、新建域控制器 二、提升为域控制器添加新林 三、新建组织单位&#xff08;OU&#xff09;&#xff0c;用户 四、将计算机加域 五、在域控中管理计算机 六、在域控中配置组策略 七、域内计算机验证组策略配置 准备工作 安装域前&#xff0c;如果有DNS…

Golang | Leetcode Golang题解之第310题最小高度树

题目&#xff1a; 题解&#xff1a; func findMinHeightTrees(n int, edges [][]int) []int {if n 1 {return []int{0}}g : make([][]int, n)deg : make([]int, n)for _, e : range edges {x, y : e[0], e[1]g[x] append(g[x], y)g[y] append(g[y], x)deg[x]deg[y]}q : []i…

二百五十二、OceanBase——Linux上安装OceanBase数据库(二)

一、目的 在OBD页面上部署OceanBase数据库时发现&#xff0c;需要把新用户也要配置ssh免密登录 二、前提 root用户已经设置免密登录 三、配置步骤 1 切换到新用户obadmin [roothurys23 ~]# su obadmin 2 执行命令生成秘钥文件 [obadminhurys23 oceanbase]$ ssh-keygen …

限免下载:715页 | 2024民营企业数字化转型典型案例集

一、前言 数字化转型不仅仅是技术的更新换代&#xff0c;它涉及到企业运营模式、组织架构、企业文化等多个层面的深刻变革。通过数字化&#xff0c;企业能够更好地理解市场动态&#xff0c;提升决策效率&#xff0c;优化客户体验&#xff0c;并最终实现业务增长和价值创造。 …

不可错过的2024翻译工具合集,提升沟通效率必备

如果你想要提升外文阅读能力&#xff0c;但是有没什么外语基础怎么办。现在有不少翻译工具可以实现整份文件进行翻译&#xff0c;让这些工具在日常生活和学习中发挥作用。 1.福昕在线翻译 链接直达&#xff1a;https://fanyi.pdf365.cn/doc 这个工具有齐全的翻译功能。可以…

利用SSE打造极简web聊天室

在B/S场景中&#xff0c;通常我们前端主动访问后端可以使用axios&#xff0c;效果很理想&#xff0c;而后端要访问前端则不能这样操作了&#xff0c;可以考虑SSE、websocket和gRPC等方式&#xff0c;实时和性能均有保障。 下面给出一个简单的例子&#xff0c;后端是nodeexpress…