当通过动态转换完成向下转换时,不会调用基 class 的虚拟析构函数

Virtual destructor of base class is not called when downcasting is done via dynamic cast

当我 运行 以下代码时,出现以下问题。 删除派生指针 d1 不会调用基 class 的析构函数。删除派生指针 d2 调用基类析构函数。为什么转换类型(动态或静态)会影响是否调用基本析构函数。

class Base  
{ 
  public :  

  Base() { std::cout<<"Base Ctr"<<std::endl; }  

  virtual ~Base() { std::cout<<"Base Dtr"<<std::endl; }
};

class Derived : public Base  
{ 
  public :  
  Derived() { std::cout<<"Derived Ctr"<<std::endl; }  

  ~Derived() { std::cout<<"Derived Dtr"<<std::endl; }
};

int main()
{  
  Derived* d1 = static_cast<Derived*>(new Base());

  delete d1;

  Derived* d2 = dynamic_cast<Derived*>(new Base());

  delete d2;
}

输出:

Base Ctr
Base Dtr
Base Ctr

注意:为了简单起见,我没有在基 class 中显示虚函数(因为基析构函数首先被设置为虚函数)。

你的 dynamic_cast 在这两种情况下都失败了,因为你不能安全地将 Base 向下转换为 Derived (你的初始对象是 Basenew Base).您应该测试动态转换的结果

if(!d1) // d1 is nullptr here
    std::cout << "Failed dynamic_cast";

删除 nullptr 是空操作,因此不会调用析构函数。

此转换失败并且 returns 一个 nullptr:

Derived* d2 = dynamic_cast<Derived*>(new Base());

原因是该对象不是 Derived 类型。然后你在 d2 上调用 delete,这是一个空操作:

delete d2; // deleting nullptr => no-op

所以,你在 d2 后面泄露了对象。

Why is the type of cast (dynamic or static) affecting whether base destructor is called or not.

不是,但是删除空指针不会调用任何析构函数。你有一个空指针,因为你试图 dynamic_cast a BaseDerived,这显然会失败。

事实上,两个指针都是这种情况,因此您问题中的输出来自您未显示的其他一些代码。调皮!

尝试:

  Base* d1 = new Derived();
  delete d1;

甚至更好:

std::unique_ptr<Base> d1 = std::make_unique<Derived>();

或者

Derived d1;
Base *b = &d1;