首页 > 编程语言 >C++ - 虚析构和纯虚析构

C++ - 虚析构和纯虚析构

时间:2023-04-14 11:35:01浏览次数:30  
标签:函数 子类 C++ Animal 父类 虚析构 纯虚析构

1. 为什么需要虚析构函数

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

#include <iostream>
#include <stdlib.h>
#include <string>

using namespace std;

class Animal {
public:

	Animal()
	{
		cout << "Animal 构造函数调用!" << endl;
	}

	virtual void Speak() = 0;

	~Animal()
	{
		cout << "Animal 析构函数调用!" << endl;
	}
};


class Cat : public Animal
{
public:

	Cat(string name)
	{
		cout << "Cat 构造函数调用!" << endl;
		m_Name = new string(name);
	}

	virtual void Speak()
	{
		cout << *m_Name << "小猫在说话!" << endl;
	}

	~Cat()
	{
		cout << "Cat 析构函数调用!" << endl;
		if (this->m_Name != NULL)
		{
			delete m_Name;
			m_Name = NULL;
		}
	}

public:
	string* m_Name;
};

void test01()
{
	Animal* animal = new Cat("Tom");
	animal->Speak();

	//通过父类指针去释放,会导致子类对象可能清理不干净,造成内存泄漏
	//怎么解决?给基类增加一个虚析构函数
	//虚析构函数就是用来解决通过父类指针释放子类对象
	delete animal;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

 

执行结果如下:

分析:

在析构的时候,只是调用了父类的析构函数,并没有调用子类的析构函数。这样,子类在堆区开辟的空间就无法释放,造成内存泄露。

 

2. 引入虚析构解决父类指针释放,子类对象在堆区空间未清理

只需要在基类析构函数前加virtual关键字即可

可以看到运行结果已经正常:

3. 纯虚析构

同一个类中,虚析构和纯虚析构只有有一个存在,将上面的虚析构改为纯虚析构:

class Animal
{
public:
 
	Animal()
	{
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;
 
	virtual ~Animal() = 0;
};
 
Animal::~Animal()
{
	cout << "Animal 纯虚析构函数调用!" << endl;
}

纯虚析构一定要有具体的实现,如果没有的话编译会报错。

 

4. 总结

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

 

1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象

2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构

3. 拥有纯虚析构函数的类也属于抽象类

标签:函数,子类,C++,Animal,父类,虚析构,纯虚析构
From: https://www.cnblogs.com/zhuchunlin/p/17317796.html

相关文章

  • 【c&c++】strdup函数简介
    strdup函数简介收藏 用法:#include<string.h> 功能:复制字符串s  说明:返回指向被复制的字符串的指针,所需空间由malloc()分配且可以由free()释放。  举例:       //strdup.c          #include<syslib.h>     #include<string.h>      mai......
  • C/C++会员卡计费管理系统[2023-04-13]
    C/C++会员卡计费管理系统[2023-04-13]1.开发一个会员卡计费管理系统。2.新会员登记(将会员个人信息及会员卡信息进行录入);3.会员信息维护、会员等级、不同等级享受折扣信息的维护;4.会员续费。(会员出示会员卡后,管理人员根据卡号查找到该会员的信息并显示,此时可以进行续费,续费......
  • c++基础入门2
    一、数组1、概述所谓数组,就是一个集合,里面存放相同类型的数据元素特点:1、数组中的每个数据元素都是相同的数据类型2、数组是由连续的内存位置组成的2、一维数组(1)、定义方式:一维数组有中定义方式:1、数据类型数组名[数据长度];2、数据类型数组名[数据长度]={值1,值2.....};3、数据......
  • 斯坦福 UE4 C++ ActionRoguelike游戏实例教程 10.控制台变量的用法 & 静态函数库 &
    斯坦福课程UE4C++ActionRoguelike游戏实例教程0.绪论概述本文对应Lecture15,61-ConsoleVariablesfordebuggingandgamebalancing。本文将会教你如何在C++中编辑控制台变量的逻辑,通过在游戏中打开控制台,以修改控制台变量的方式来修改游戏里的各种参数;此外,还会使用自......
  • C++ // 2023/4/13
    stl**序列式容器**:强调值的排序,序列式容器中的每个元素均有固定的位置。  **关联式容器**:二叉树结构,各元素之间没有严格的物理上的顺序关系质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等非质变算法:是指运算过程中不会更改区间内的元素内容......
  • C++课本第三章例题
    3-2输入一个8位二进制数,将其转换为十进制数输出。1#include<iostream>2usingnamespacestd;3doublepower(doublex,intn);//函数的声明,double类型防止超出整型4intmain()5{6intnumber=0;7for(inti......
  • C++ 中的数组
    数组的声明与定义数组是一种复合类型。数组的声明形如**a[d]**其中a是数组的名字,d是数组的维度。维度说明数组中元素的个数,因此必须大于0数组中的元素个数也是属于数组类型的一部分,编译的时候应该是已知的,也就是说,维度必须是一个常量表达式unsignedcnt=42; //......
  • c++打卡第四天
    一、题目描述。  实现一个简单的程序,运行时显示“Menu:A(dd) D(elete)S(ort)Q(uit),Selectone:"提示用户输入,A代表增加,D表示删除,S表示排序,Q代表推出,输入为ASD时分别提示“数据已经增加、删除、排序。”输入为Q时程序结束。①要求用ifelse语句判断,用breakcontinue控......
  • c++指导书
    [实验任务四]:****电子钟设计一款电子钟类,用于显示时、分、秒实验要求:\1.含有形参有默认值的默认构造函数;\2.重载前缀++和后缀—用于调整时间,每次调整均对秒进行调整,若秒满60,则分加1,若分满60则时加1,时满24,则清零重新开始;\3.重载插入运算符>>用于输入(设定)时间;\4.重载......
  • C++从0到1 —— 跟着我一定能学会
    1.阅读须知以下所有的内容都属于我的个人总结与思考,但同时又想作为一种资源供大家学习、参考。文章的水平和质量可能不是很高,也有可能内容有些小错误,希望各位读者能够私信我指出错误。C++的部分分为三个版块:C++基础知识部分、STL部分、C++11特性以及其他。2.C++基础知识 ......