一、问题示例
            
            
              cpp
              
              
            
          
          #include <iostream>
using namespace std;
class Base {
public:
    Base() { cout << "Base constructor\n"; }
    ~Base() { cout << "Base destructor\n"; } // 不是 virtual
};
class Derived : public Base {
public:
    Derived() { cout << "Derived constructor\n"; }
    ~Derived() { cout << "Derived destructor\n"; }
};
int main() {
    Base* ptr = new Derived();  // 用 Base 指针指向 Derived 对象
    delete ptr;                 // 只调用 Base 的析构函数
    return 0;
}二、输出结果

注意:没有调用 Derived 的析构函数
三、问题解释
为什么会这样?
- 
Base的析构函数不是virtual;
- 
当你执行 delete ptr,编译器只看ptr的静态类型(即Base*),它就只调用~Base();
- 
因此,不会调用 Derived的析构函数,可能会导致:- Derived析构中释放的资源没有释放(内存泄漏);
- 或者 Derived析构中有清理逻辑没执行(行为错误);
 
四、修复方法
将 Base 的析构函数设为 virtual:
            
            
              cpp
              
              
            
          
          class Base {
public:
    virtual ~Base() { cout << "Base destructor\n"; }  // virtual 析构
};正确输出:

五、图示原理(简化)
如果你用 virtual :
Base vtable:
+----------------+
|  &Base::~Base  |  ← 原始虚函数地址
+----------------+
Derived vtable:
+--------------------+
| &Derived::~Derived | ← 覆盖虚析构函数
+--------------------+
delete ptr 会通过 vtable 跳转到 Derived::~Derived → 再调用 Base::~Base六、总结
| 是否 virtual | delete 派生类指针时行为 | 是否内存泄漏 | 
|---|---|---|
| 否 | 只调用基类析构函数 | 有可能 | 
| 是 | 调用派生 → 再基类析构 | 安全 | 
七、经验建议
只要类中有虚函数(即打算支持多态)或你"可能"通过基类指针删除派生类对象,就应该将析构函数声明为
virtual。
最好这样写:
            
            
              cpp
              
              
            
          
          class Base {
public:
    virtual ~Base() = default;
};