通过动态强制转换完成向下转换时,不会调用基类的虚析构函数

时间:2015-05-24 16:06:13

标签: c++ casting downcast

当我运行以下代码时,我遇到以下问题。 删除派生指针d1不会调用基类的析构函数。删除派生指针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

注意:为了简单起见,我没有在基类中显示虚函数(因为基础析构函数首先是虚拟的)。

4 个答案:

答案 0 :(得分:1)

此演员表失败并返回nullptr

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

原因是该对象不属于Derived类型。然后,您在delete上致电d2,这是一个无操作:

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

因此,您将对象泄漏到d2后面。

答案 1 :(得分:0)

您的dynamic_cast在两种情况下均失败,因为您无法安全地将Base向下转换为Derived(您的初始对象为Basenew Base) 。你应该测试动态演员的结果

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

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

答案 2 :(得分:0)

  

为什么类型的强制转换(动态或静态)会影响是否调用基础析构函数。

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

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

答案 3 :(得分:-2)

尝试:

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

甚至更好:

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

或者

Derived d1;
Base *b = &d1;