当我运行以下代码时,我遇到以下问题。 删除派生指针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
注意:为了简单起见,我没有在基类中显示虚函数(因为基础析构函数首先是虚拟的)。
答案 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
(您的初始对象为Base
,new Base
) 。你应该测试动态演员的结果
if(!d1) // d1 is nullptr here
std::cout << "Failed dynamic_cast";
删除nullptr
是一个无操作,因此不会调用析构函数。
答案 2 :(得分:0)
为什么类型的强制转换(动态或静态)会影响是否调用基础析构函数。
不是,但删除空指针不会调用任何析构函数。您有一个空指针,因为您尝试dynamic_cast
Base
到Derived
,这显然会失败。
实际上,对于两个指针都是这种情况,因此您的问题中的输出来自您未显示的其他一些代码。淘气!
答案 3 :(得分:-2)
尝试:
Base* d1 = new Derived();
delete d1;
甚至更好:
std::unique_ptr<Base> d1 = std::make_unique<Derived>();
或者
Derived d1;
Base *b = &d1;