c++多态(3) -- 虚析构函数

代码:  

enum class _ANIMALS_TYPE {
	CAT,
	DOG,
	ANIMAL_COUNT
};

class Animal {
public:
	Animal(_ANIMALS_TYPE  type, int age,const char* name);
	~Animal();
	virtual void eat()const = 0;
private:
	_ANIMALS_TYPE  type;   // 动物类型
	int age;               // 动物年龄
	char* name = NULL;
};

class CAT : public Animal {
public:
	CAT(_ANIMALS_TYPE  type, int age, const char* name,const char* love);
	~CAT();
	void eat()const override;
private:
	char* love = NULL;
};

int main(void) {
	Animal* f = new CAT(_ANIMALS_TYPE::CAT, 5, "小猫", "小美");
	delete f;

	system("pause");

	return 0;
}

Animal::Animal(_ANIMALS_TYPE type, int age, const char* name)
{
	this->type = type;
	this->age = age;

	if (this->name) {
		delete this->name;
	}

	int len = strlen(name) + 1;

	this->name = new char[len];
	strncpy(this->name, name, len);
}

Animal::~Animal()
{
	cout << "调用Animal类的析构函数" << endl;

	// 如果name非空释放内存
	if (name) {
		delete name;
	}
}

CAT::CAT(_ANIMALS_TYPE type, int age,const char*name,const char*love):Animal(type,age,name)
{
	if (this->love) {
		delete this->love;
	}

	int len = strlen(love) + 1;
	this->love = new char[len];
	strncpy(this->love, love, len);
}

CAT::~CAT()
{
	cout << "调用CAT类的析构函数" << endl;
	if (love) {
		delete love;
	}
}

void CAT::eat() const
{
	cout << "猫猫吃猫粮" << endl;
}

代码分析:   

1.    我们之前讲过,如果类内部有开辟空间,那么就需要在析构函数中释放空间,上面就是这种情况,我们在父类和子类中都开辟了内存,并且在析构函数中释放了内存。

2.   我们使用多态的原则(使用父类的指针指向子类的对象),代码中我们使用new开辟了一片子类内存,然后使用父类指针指向了子类的这片内存。 

3.  当开辟子类的内存时,会调用子类和父类的构造函数,那么就会给name和love属性开辟空间。 

4.  我们给父类指针开辟空间之后,使用结束就要释放这个指针。 因为在类中有开辟空间,释放是就需要调用析构函数,将申请的内存释放掉。 

 c++多态(3) -- 虚析构函数_第1张图片

5.  因为我们在申请内存的时候,父类的name和子类的love都开辟了内存,按理来说释放的时候都应该释放带哦,但是如图,释放时,只调用了父类的析构函数,也就是只释放了name。 

这种情况,明显有问题,子类申请的内存不释放,就会造成内存泄露的风险。 

原因: 

其实和之前的原因类似,就是虽然我们使用父类的指针指向了子类,但是指针是父类的,在释放内存的时候自然只会调用父类的析构函数。 

解决方法: 

和之前的解决方式一样,就是在父类析构函数前加上virtual,实现虚析构函数。至于为什么,那就和之前的虚函数是类似的了。 

 加上之后: 

c++多态(3) -- 虚析构函数_第2张图片 c++多态(3) -- 虚析构函数_第3张图片 

这样在父类指针指向子类内存的时候,释放父类指针,不仅会调用父类的析构函数,也会调用子类的析构函数。 

代码技巧: 

为了防止上面的情况出现,我们建议如果一个类又子类就将析构函数加上virtual,如果有上面的情况,自然不会出问题,如果没有,加上也不影响。 

你可能感兴趣的:(c++,开发语言)