在多态使用的过程中,如果子类有数据开辟到了堆区,那么父类指针或者引用在释放的时候无法调用到子类的析构函数。

解决方法:将父类的析构函数修改成为虚析构或者纯虚析构函数

虚析构和纯虚析构:

  • 都可以解决子类堆区数据无法释放的问题
  • 都需要具体的函数实现
    • 虚析构可以直接在类中实现
    • 纯虚析构需要在类外,加上类作用域实现

如果类中有纯虚析构函数,那么该类也属于抽象类,无法实例化对象

一、虚析构

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Animal{
  5. public:
  6. Animal(){
  7. cout << "Animal构造函数的调用" << endl;
  8. }
  9. virtual ~Animal(){ // 虚析构函数的声明和实现
  10. cout << "Animal 析构函数的调用" << endl;
  11. }
  12. virtual void speak(){
  13. cout << "Animal在说话" << endl;
  14. }
  15. };
  16. class Cat:public Animal{
  17. public:
  18. string* str;
  19. Cat(string name){
  20. str = new string(name);
  21. cout << "Cat的构造函数调用" << endl;
  22. }
  23. ~Cat(){
  24. if(str != NULL){
  25. cout << "Cat析构函数调用" << endl;
  26. delete str;
  27. str = NULL;
  28. }
  29. }
  30. void speak(){
  31. cout << *str << " 在说话" << endl;
  32. }
  33. };
  34. void doSpeak(){
  35. // Animal* animal = new Cat("cat");
  36. Animal& animal = *(new Cat("cat"));
  37. animal.speak();
  38. delete &animal;
  39. }
  40. int main(){
  41. doSpeak();
  42. return 0;
  43. }

二、纯虚析构

纯虚析构函数是在父类中只有声明,定义需要在父类外部且要加上的父类的作用域符号

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class Animal{
  5. public:
  6. Animal(){
  7. cout << "Animal构造函数的调用" << endl;
  8. }
  9. virtual ~Animal() = 0; // 纯虚析构的声明
  10. virtual void speak(){
  11. cout << "Animal在说话" << endl;
  12. }
  13. };
  14. Animal::~Animal(){ // 纯虚析构的定义
  15. cout << "Animal纯析构函数的调用" << endl;
  16. }
  17. class Cat:public Animal{
  18. public:
  19. string* str;
  20. Cat(string name){
  21. str = new string(name);
  22. cout << "Cat的构造函数调用" << endl;
  23. }
  24. ~Cat(){
  25. if(str != NULL){
  26. cout << "Cat析构函数调用" << endl;
  27. delete str;
  28. str = NULL;
  29. }
  30. }
  31. void speak(){
  32. cout << *str << " 在说话" << endl;
  33. }
  34. };
  35. void doSpeak(){
  36. // Animal* animal = new Cat("cat");
  37. Animal& animal = *(new Cat("cat"));
  38. animal.speak();
  39. delete &animal;
  40. }
  41. int main(){
  42. doSpeak();
  43. return 0;
  44. }

类中包含有纯虚析构的话,那么该类为抽象类,无法实例化对象

image.png**