cpp_destructor_virtual - ShenYj/ShenYj.github.io GitHub Wiki

虚析构函数

  • 如果存在父类指针指向子类对象的情况,应该将析构函数声明为虚函数(虚析构函数)
    • delete父类指针时,才会调用子类的析构函数,保证析构的完整性

      struct Animal {
      
          void speak() {
              cout << "Animal::speak()" << endl;
          }
      
          void run() {
              cout << "Animal::run()" << endl;
          }
      
          ~Animal() {
              cout << "Animal::~Animal()" << endl;
          }
      };
      
      struct Cat: Animal {
      
          void speak() {
              cout << "Cat::speak()" << endl;
          }
      
          void run() {
              cout << "Cat::run()" << endl;
          }
      
          ~Cat() {
              cout << "Cat::~Cat()" << endl;
          }
      };
      
      int main() {
      
          Animal *cat = new Cat();
          cat->speak();   /// 打印结果  Animal::speak()
      
          /// 回收堆空间内存, 会调用析构函数
          delete cat;     /// 打印结果  Animal::~Animal()
      
          /// 完整打印结果
          /// Animal::Animal()
          /// Car::Cat()
          /// Animal::speak()
          /// Animal::~Animal()
      }

      通过log观察, Cat的析构没有调用; 因为没有虚函数,不存在虚表, delete的时候就根据左侧 Animal 的类型去执行析构

      • 将析构声明为虚函数

        struct Animal {
        
            void speak() {
                cout << "Animal::speak()" << endl;
            }
        
            void run() {
                cout << "Animal::run()" << endl;
            }
        
            virtual ~Animal() {
                cout << "Animal::~Animal()" << endl;
            }
        };
        
        struct Cat: Animal {
        
            void speak() {
                cout << "Cat::speak()" << endl;
            }
        
            void run() {
                cout << "Cat::run()" << endl;
            }
        
            ~Cat() {
                cout << "Cat::~Cat()" << endl;
            }
        };
        
        int main() {
        
            Animal *cat = new Cat();
            cat->speak();
            delete cat;     
        
            /// 完整打印结果
            /// Animal::Animal()
            /// Car::Cat()
            /// Animal::speak()
            /// Cat::~Cat()
            /// Animal::~Animal()
        }

        加上虚函数,成功的调用了 Cat 和 Animal 的析构函数

⚠️ **GitHub.com Fallback** ⚠️