C++ 虚析构函数和纯虚析构函数

本文深入探讨了C++中虚析构函数和纯虚析构函数的概念及应用,特别是在多态环境中如何避免内存泄漏问题。通过具体代码示例,详细解释了父类指针指向子类对象时,虚析构函数和纯虚析构函数如何确保子类析构函数被正确调用,从而释放堆区分配的空间。

#include <iostream>

using namespace std;

/************************************************************************/
/*
虚析构函数和纯虚析构函数
1.当父类指针或引用指向子类对象时,若子类中数据成员有在堆区申请空间,父类析构函数需要
声明为虚析构函数或纯虚析构函数,析构时子类的析构函数会被调用,堆区空间会被释放,否则子类对象会出现内存泄漏问题
2.纯虚析构函数需要进行声明和类外定义,否则编译器或报错
/************************************************************************/
class Animal
{
public:
	 Animal()
	 {
		 cout<<"Animal构造函数"<<endl;
	 }

	 //父类虚成员函数
	 virtual void speak()
	 {
		 cout<<"动物在讲话调用"<<endl;
	 }
/*
	//非虚析构函数,父类指针或引用指向子类对象时,只会调用父类析构函数,导致子类析构函数未调用,堆区内存泄漏
	 ~Animal()
	 {
		 cout<<"Animal析构函数调用"<<endl;
	 }
*/
	 
/*	 //虚析构函数可以解决子类对象堆区空间未释放问题
	 //父类指针或引用指向子类对象时,先调用父类构造函数,再调用子类构造函数;析构时,先调用子类析构函数,再调用父类析构函数
	 virtual ~Animal()
	 {
		 cout<<"Animal虚析构函数调用"<<endl;
	 }
*/

	 //纯虚析构函数也可以达到虚析构同样效果,不但需要声明,还需要有定义
	 //因为含有纯虚成员函数的类为抽象类,无法实例化,但析构时先调用子类析构函数,再调用父类析构函数,所有需要析构函数的定义(函数体),即使是纯虚析构函数
	 virtual ~Animal()=0;
};
Animal::~Animal()
{
	cout<<"Animal纯虚析构函数调用"<<endl;
}

class Cat:public Animal
{
public:
	//有参构造函数,在堆区申请空间
	Cat(string name)
	{
		cout<<"Cat构造函数调用"<<endl;
		m_name = new string(name);
	}

	virtual void speak()
	{
		cout<<"猫在讲话"<<endl;
	}
	
	~Cat()
	{
		cout<<"Cat析构函数调用"<<endl;
		if (m_name != NULL)
		{
			delete m_name;
			m_name = NULL;
		}
	}
	string *m_name;
};


void dospeak(Animal *pmal)
{
	pmal->speak();

	
	delete pmal;
}


void test1()
{
	
	dospeak(new Cat("Tom"));

}

int main()
{
	test1();

	return 0;	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值