C++Note 虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:
可以解决父类指针释放子类对象
都需要有具体的函数实现
虚析构和纯虚析构区别:
如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:
virtual ~类名(){}
纯虚析构语法:
virtual ~类名() = 0;//类内纯虚构
类名::类名(){}//作用域 + 类名
虚析构之前:
1 class Animal 2 { 3 public: 4 Animal() 5 { 6 cout << "Animal的构造函数调用" << endl; 7 } 8 ~Animal() 9 { 10 cout << "Animal的析构函数调用" << endl; 11 } 12 virtual void speak() = 0; 13 14 }; 15 class Cat :public Animal 16 { 17 public: 18 Cat(string name) 19 { 20 cout << "Cat的构造函数调用" << endl; 21 m_Name = new string(name); 22 } 23 virtual void speak() 24 { 25 cout << *m_Name <<"猫叫" << endl; 26 } 27 ~Cat() 28 { 29 if (m_Name != NULL) 30 { 31 cout << "Cat的析构函数调用" << endl; 32 delete m_Name; 33 m_Name = NULL; 34 } 35 } 36 string* m_Name; 37 }; 38 void test() 39 { 40 Animal* animal = new Cat("Tim"); 41 animal->speak(); 42 //父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露 43 delete animal; 44 }
输出:

虚析构之后:
1 class Animal 2 { 3 public: 4 Animal() 5 { 6 cout << "Animal的构造函数调用" << endl; 7 } 8 //利用虚析构可以解决 父类指针释放自类对象时不干净的问题 9 virtual ~Animal() 10 { 11 cout << "Animal的析构函数调用" << endl; 12 } 13 virtual void speak() = 0; 14 };
结果输出:

纯虚析构:
1 class Animal 2 { 3 public: 4 Animal() 5 { 6 cout << "Animal的构造函数调用" << endl; 7 } 8 virtual ~Animal() = 0;//纯虚析构 9 virtual void speak() = 0; 10 };
但是此时报错:无法解析的外部命令( 链接阶段报错) 预处理、编译、汇编、链接
此时纯虚析构只是一个声明,无代码实现,但析构函数有执行,(父类中也可能也有数据开辟到堆区,此时父类中析构函数实现起到作用)
虚析构 或 纯虚析构都需要代码实现
1 class Animal 2 { 3 public: 4 Animal() 5 { 6 cout << "Animal的构造函数调用" << endl; 7 } 8 virtual ~Animal() = 0;//纯虚析构 需要声明 也需要实现 9 virtual void speak() = 0; 10 }; 11 Animal::~Animal() 12 { 13 cout << "Animal的析构函数调用" << endl; 14 }
总结:
1.虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
2.如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
3.拥有纯虚析构函数的类也属于抽象类
浙公网安备 33010602011771号