【b站黑马程序员C++视频学习笔记-虚析构和纯虚析构】

虚析构和纯虚析构

多态使用的时候,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。因为这时如果删除父类指针指向的子类对象就不会触发动态绑定,只会调用父类的析构函数,而不会调用子类的析构函数,那么子类申请的空间就得不到释放了,会发生内存泄露
解决办法:将父类中的析构函数改为虚析构或纯虚析构
虚析构和纯虚析构的共性:

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

虚析构和纯虚析构的区别:
有纯虚函数的类属于抽象类,无法实例化对象

虚析构语法:
virtual ~类名(){}
纯虚析构语法:
virtual ~类名() = 0;
类名::~类名(){}

先写出以下代码看看运行结果:

#include
using namespace std;
#include

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

class Cat:public Animal
{
public:
	Cat(string name) {//构造函数
		cout << "Cat构造函数调用!" << endl;
		mName=new string(name);//把字符串创建在堆区,并且让一个指针区维护堆区的数据
	}

	virtual void speak() {
		cout << *mName<<"小猫在喵喵叫" << endl;
	}

	~Cat() {//析构函数
		if (mName != NULL) {
			cout << "Cat析构函数调用!" << endl;
			delete mName;
			mName = NULL;
		}
	}

	string *mName;//指针
};

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

int main() {
	test01();

	system("pause");

	return 0;
}

运行结果为:
【b站黑马程序员C++视频学习笔记-虚析构和纯虚析构】_第1张图片
可见,只调用了父类Animal的析构函数,并没有调用子类Cat的析构函数,所以需要对代码进行修改
利用虚析构解决:
~Animal()前面加上关键字virtual


	//利用虚析构解决父类指针释放子类对象时释放不干净的问题
	virtual ~Animal() {
		cout << "Animal析构函数调用!" << endl;
	}

运行结果为:
【b站黑马程序员C++视频学习笔记-虚析构和纯虚析构】_第2张图片
利用纯虚析构解决:

//虚析构和纯虚析构
class Animal
{
public:
	Animal() {
		cout << "Animal构造函数调用!" << endl;
	}

	//利用虚析构解决父类指针释放子类对象时释放不干净的问题
	//virtual ~Animal() {
	//	cout << "Animal析构函数调用!" << endl;
	//}
	
	//纯虚析构
	virtual ~Animal() = 0;

	//纯虚函数
	virtual void speak() = 0;
};

Animal:: ~Animal() {//纯虚析构的实现
	cout << "Animal纯虚析构函数调用!" << endl;
}

使用纯虚析构时,不仅要声明,而且要在类外实现
运行结果:
【b站黑马程序员C++视频学习笔记-虚析构和纯虚析构】_第3张图片

你可能感兴趣的:(c++,音视频,学习)