当通过动态转换完成向下转换时,不会调用基 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
(你的初始对象是 Base
,new 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 Base
到 Derived
,这显然会失败。
事实上,两个指针都是这种情况,因此您问题中的输出来自您未显示的其他一些代码。调皮!
尝试:
Base* d1 = new Derived();
delete d1;
甚至更好:
std::unique_ptr<Base> d1 = std::make_unique<Derived>();
或者
Derived d1;
Base *b = &d1;
当我 运行 以下代码时,出现以下问题。 删除派生指针 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
(你的初始对象是 Base
,new 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 Base
到 Derived
,这显然会失败。
事实上,两个指针都是这种情况,因此您问题中的输出来自您未显示的其他一些代码。调皮!
尝试:
Base* d1 = new Derived();
delete d1;
甚至更好:
std::unique_ptr<Base> d1 = std::make_unique<Derived>();
或者
Derived d1;
Base *b = &d1;