虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:
virtual ~类名(){}
纯虚析构语法:
virtual ~类名() = 0;
类名::~类名(){}

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class AbstractAnimal{
  5. public:
  6. AbstractAnimal() {
  7. cout << "AbstractAnimal Constructed" << endl;
  8. }
  9. virtual void Speak() = 0;
  10. //父类析构如果存在,不会走子类析构
  11. //只有将其虚拟化后,才能走子类的析构
  12. //利用虚析构可以解决父类指针释放子类对象不干净的问题
  13. virtual ~AbstractAnimal() = 0;
  14. }; //纯虚析构会解决问题,但是在编译器中
  15. //纯虚析构必须存在,被虚拟化后必须有实现的方式。
  16. AbstractAnimal::~AbstractAnimal() {
  17. //不可是空代码
  18. //必须实现。
  19. cout << "Pure Vitural AbstractAnimal Destructed" << endl;
  20. }
  21. class Cat:public AbstractAnimal{
  22. public:
  23. Cat(string name) {
  24. this->m_Name = new string(name);
  25. cout << "Cat Constructed" << endl;
  26. }
  27. void Speak() {
  28. cout << *m_Name << " is speaking" << endl;
  29. }
  30. string *m_Name;
  31. ~Cat() {
  32. if (m_Name != NULL) {
  33. delete m_Name;
  34. m_Name = NULL;
  35. }
  36. cout << "Cat Destructed" << endl;
  37. }
  38. };
  39. void DoSpeak(AbstractAnimal* abs) {
  40. abs->Speak();
  41. delete abs;
  42. }
  43. void example() {
  44. DoSpeak(new Cat("Tom"));
  45. }
  46. int main() {
  47. example();
  48. return 0;
  49. }

总结:
1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
3. 拥有纯虚析构函数的类也属于抽象类