0
点赞
收藏
分享

微信扫一扫

C++基类指针释放无法调用派生类析构代码

夜空一星 2022-02-18 阅读 70
c++

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

#include <iostream>
using namespace std;
#include <string>

class Animal {
public:

	Animal()
	{
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;

	//析构函数加上virtual关键字,变成虚析构函数
	 ~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;
}

运行结果:

        我们在Cat类中通过堆区开辟内存,打算在析构函数中释放。然而从运行结果可以看出,Cat的析构函数没有被调用,因此现在代码会造成内存泄漏

为了解决这个问题,可以将基类中的析构函数改为**虚析构** 或者** 纯虚析构**.

更改后的代码如下:

#include <iostream>
using namespace std;
#include <string>

class Animal {
public:

	Animal()
	{
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;

	//析构函数加上virtual关键字,变成虚析构函数
	//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 << *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;
}

运行结果:

 发现成功调用Cat类的析构函数,释放掉了堆区开辟的内存。

总结:

//多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
//解决方式:将父类中的析构函数改为**虚析构**或者**纯虚析构**

虚析构和纯虚析构共性:

* 可以解决父类指针释放子类对象

* 都需要有具体的函数实现

虚析构和纯虚析构区别:

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

举报

相关推荐

0 条评论