虚析构和纯虚析构----->解决子类析构函数调不到的问题
在多态的使用时,如果子类中有属性开辟到堆区,那么父类子针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
析构和纯虚析构共性:
1、 可以解决父类指针释放子类对象
2、 都需要有具体的函数实现
区别:
如果是纯虚析构,该类属于抽象类,无法实例化对象
class Animal{
public:
Animal(){
printf("动物类构造函数!\n");
}
// 利用虚析构可以解决父类指针释放子类对象不干净的问题
// virtual ~Animal(){
// cout<<"动物类析构函数"<<endl;
// }
// 纯虚析构函数 既需要声明,也需要实现
// 有了纯虚析构 该类也是抽象类了,无法实例化对象
virtual ~Animal() =0;
//
virtual void speak(){
cout<<"hello"<<endl;
}
};
// 纯虚析构的实现,可以释放父类在堆区开辟的变量
Animal::~Animal(){
cout<<"动物类析构函数,在此释放父类在堆区开辟的变量!"<<endl;
}
class Dog:public Animal{
public:
string *m_Name;
Dog(string name){
// 子类有属性开辟到堆区
m_Name = new string(name);
cout<<"子类"<<*m_Name<<"构造函数!\n";
}
~Dog(){
cout<<"狗类析构函数"<<endl;
if (m_Name!=NULL) {
delete m_Name;
m_Name = NULL;
}
}
void speak(){
cout<<"汪汪汪"<<endl;
};
};
void demo(){
// Animal an; // 无法实例化对象了哦
Animal *animal = new Dog("大黄");
// 父类指针在析构的时候,不会调用子类的析构函数,导致如果子类在堆区有属性,出现内存泄漏
animal->speak();
delete animal;
}
int main(int argc, const char * argv[]) {
demo();
return 0;
}
总结
1、虚析构和纯虚析构就是用来解决通过父类指针释放子类对象
2、如果子类中没有堆区数据,可以不用虚虚构和纯虚析构
3、拥有纯虚析构函数的类也属于抽象类