/*本文档记录 虚析构函数 和 纯虚析构函数的使用
虚析构函数和纯虚析构函数,主要应用于子类对象需要释放堆区内存空间,
使用多态,是父类指针指向子类对象,在释放父类指针之后,子类的析构函数是不调用的,
解决方案是:父类使用虚析构函数 或 纯虚函数,则子类的析构函数可被自动调用*/
#include <iostream>
using namespace std;
#include <string>
class Animal{
public:
Animal(){
cout<<"父类的构造函数在运行"<<endl;
}
// ~Animal(){
// cout<<"父类的析构函数在运行"<<endl;
// }
// //需要使用 虚析构函数(如下);否则子类的析构函数不会被调用
// virtual ~Animal(){
// cout<<"父类的析构函数在运行"<<endl;
// }
//或者可以使用 纯虚析构函数(如下):
//纯虚析构函数在类内声明,在类外初始化,不然会报错
virtual ~Animal() = 0;
virtual void speak() = 0;//纯虚函数
};
Animal::~Animal(){//类外初始化,可以去掉关键字virtual;
//标注好作用域:Animal::
cout<<"父类的析构函数在运行"<<endl;
}
class Cat:public Animal{
public:
string * p_name;//子类成员变量是一个字符串指针
Cat(string s){
cout<<"子类的构造函数在运行"<<endl;
p_name =new string (s);//p_name是字符串指针变量,将其赋值
}
~Cat(){
cout<<"子类的析构函数在运行"<<endl;
//因为子类对象创建在堆区,需要对子类对象
if(p_name != NULL){
delete p_name;
p_name = NULL;
}
}
void speak(){//纯虚函数,子类重写
cout<<"小猫"<<*p_name<<"在说话"<<endl;//指针成员变量解引用,获取小猫名字值
}
};
void test(){
Animal * a = new Cat("Tom");//父类指针a指向堆区内Cat对象的内存空间
//1.在堆区创建了一个Cat对象,且父类Animal指针指向它
//2.子类继承了父类的纯虚函数speak(),并进行了重写
//3.调用子类的函数speak()
a->speak();
delete a;
}
int main(){
test();
}