多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:1.可以解决父类指针释放子类对象 2.都需要有具体的函数实现
虚析构和纯虚析构区别:如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:virtual ~类名(){}
纯虚析构语法:virtual ~类名()=0;
补充:实例化是指在面向对象的编程中,把用类创建对象的过程称为实例化。 是将一个抽象的概念类,具体到该类实物的过程。 实例化过程中一般由类名 对象名 = new 类名(参数1,参数2...参数n)构成。 如 Date date=new Date ();就是用日期类创建了一个日期的对象,就叫对象的实例化
#include<iostream>
using namespace std;
#include<string>
class Animal
{
public:
Animal()
{
cout << "Animal 构造函数调用 " << endl;
}
//利用虚析构可以解决,父类指针释放子类对象时不干净的问题
//virtual~Animal()
//{
// cout << "Animal 析构函数调用 " << endl;
//}
//纯虚析构,需要声明也需要实现
//有了纯虚析构后,这个类也属于抽象类,无法实例化对象
virtual~Animal()= 0;
//纯虚函数
virtual void speak() = 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 << " cat speak" << endl;
}
string * m_Name;//指针
~Cat()
{
if (m_Name != NULL)
{
cout << "Cat 析构函数调用 " << endl;
delete m_Name;
m_Name = NULL;
}
}
};
void test01()
{
Animal * animal = new Cat("Tom");//父类指向子类对象
animal->speak();
//父类指针在析构时,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露
//解决办法:Animal改为虚析构
delete animal;
}
int main()
{
test01();
system("pause");
return 0;
}