C++多态虚析构和纯虚析构的实现

 更新时间:2023年09月06日 08:55:03   作者:Love coldplay  
本文主要介绍了C++多态虚析构和纯虚析构的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码注释:父类指针在释放时,只会调用父类自己的析构函数,而无法调用子类的析构函数

解决方式:将父类的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

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

虚析构和纯虚析构区区别:

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

为什么需要虚析构

#include<iostream>
#include<string>
using namespace std;
//虚析构和纯虚析构
class Animal
{
public:
	Animal()
	{
		cout << "调用了父类的构造函数" << endl;	
	}
	~ Animal()
	{
		cout << "调用了父类的析构函数" << endl;
	}
	virtual void speak() = 0;//纯虚函数
};
class Cat :public Animal
{
public:
	string *m_Name;
	//在子类的构造函数,加入小猫的姓名
	Cat(string name)
	{
		cout << "调用了子类-小猫类的构造函数" << endl;
		m_Name = new string(name);//在堆区创建
	}
	~Cat()
	{
		if (m_Name != NULL)
		{
			delete m_Name;
			m_Name = NULL;
			cout<<"调用了子类-小猫类的析构函数"<<endl;
		}
	}
	virtual void speak()
	{
		cout << *m_Name<<"小猫在说话" << endl;//解引用
	}
};
void testSpeak()
{
	Animal *animal = new Cat("Tom");//有参构造函数
	animal->speak();
	delete animal;
}
int main()
{
	testSpeak();
}

结果:

没有调用子类的构造函数

原因:是因为我们用父类指针指向了子类对象,所以释放父类指针时,并不会调用子类的析构代码

父类指针在析构时候 不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄漏

解决办法:

在父类析构函数前加入关键字 virtual

//虚析构和纯虚析构
class Animal
{
public:
	Animal()
	{
		cout << "调用了父类的构造函数" << endl;	
	}
	virtual ~ Animal()
	{
		cout << "调用了父类的析构函数" << endl;
	}
	virtual void speak() = 0;//纯虚函数
};

虚析构函数用途

可以利用虚析构函数解决父类指针在释放子类问题时,内存存在泄露的问题

纯虚析构

纯虚析构既要声明也需要实现

  • 类内声明
  • 类外定义实现

有了纯虚析构 之后 ,这个类也属于抽象类,无法实例化对象

属性开辟到了堆区

//虚析构和纯虚析构
class Animal
{
public:
	Animal()
	{
		cout << "调用了父类的构造函数" << endl;	
	}
	//virtual ~ Animal()
	//{
	//	cout << "调用了父类的析构函数" << endl;
	//}
	virtual ~Animal() = 0;//纯虚析构
	virtual void speak() = 0;//纯虚函数
};
Animal::~Animal()
{
	cout << "调用了父类的纯虚析构函数" << endl;
}

结果

总结:

  • 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  • 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
  • 拥有纯虚析构函数的类也属于抽象类

到此这篇关于C++多态虚析构和纯虚析构的实现的文章就介绍到这了,更多相关C++多态虚析构和纯虚析构内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++与namespace有关的两个编译错误的讲解

    C++与namespace有关的两个编译错误的讲解

    今天小编就为大家分享一篇关于C++与namespace有关的两个编译错误的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • 新手socket编程入门详解指南

    新手socket编程入门详解指南

    本文,将一步一步引导初学者来学习socket,所有编程思路都结合在socket API里面,以及提供socket的疑问和基础知识点,同时在最后给出多个例程,下面可以和小编一起学习
    2019-05-05
  • C++学习进阶篇之类大小计算和this指针

    C++学习进阶篇之类大小计算和this指针

    this是C++中的一个关键字,也是一个const指针,它指向当前对象,通过它可以访问当前对象的所有成员,下面这篇文章主要给大家介绍了关于C++学习进阶篇之类大小计算和this指针的相关资料,需要的朋友可以参考下
    2023-04-04
  • 深入讲解C++数据类型转换的相关函数的知识

    深入讲解C++数据类型转换的相关函数的知识

    这篇文章主要介绍了深入讲解C++数据类型转换的相关函数的知识,包括类型转换运算符函数等内容,需要的朋友可以参考下
    2015-09-09
  • 解析四方定理的应用

    解析四方定理的应用

    所有自然数至多只要用四个数的平方和就可以表示
    2013-05-05
  • 解析C语言结构体及位段

    解析C语言结构体及位段

    今天小编就为大家分享一篇关于解析C语言结构体及位段,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • OpenMP task construct 实现原理及源码示例解析

    OpenMP task construct 实现原理及源码示例解析

    这篇文章主要为大家介绍了OpenMP task construct 实现原理及源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 详解C/C++内存区域划分(简而易懂)

    详解C/C++内存区域划分(简而易懂)

    C/C++中,内存主要分为、堆、栈、全局/静态存储区和常量存储区。本文重点给大家介绍C/C++内存区域划分的相关知识,需要的朋友参考下吧
    2021-06-06
  • C/C++解析文件名和目录路径的方法

    C/C++解析文件名和目录路径的方法

    #include <libgen.h> 是一个 C/C++ 语言的头文件,主要用于字符串处理,特别是在处理文件路径时,它提供了一些函数来帮助你解析文件名和目录路径,本文就给大家介绍一下C/C++解析文件名和目录路径的方法,需要的朋友可以参考下
    2024-10-10
  • 举例讲解C语言程序中对二叉树数据结构的各种遍历方式

    举例讲解C语言程序中对二叉树数据结构的各种遍历方式

    这篇文章主要介绍了举例讲解C语言程序中对二叉树数据结构的各种遍历方式,先序中序后序二叉树遍历几乎成了最老生常谈的数据结构基础知识,的朋友可以参考下
    2016-04-04

最新评论