考虑以下示例:
#include <iostream>
class Base
{
public:
Base() { std::wcout << L"Base cons" << std::endl; }
~Base() { std::wcout << L"Base des" << std::endl; }
};
class Derived : public Base
{
public:
Derived() { std::wcout << L"Derived cons" << std::endl; }
~Derived() { std::wcout << L"Derived des" << std::endl; }
};
int main()
{
Base * derived = new Derived;
std::wcout << L"Deleting..." << std::endl;
delete derived; // Base::~Base() is not virtual so only Base::~Base() is called
return 0;
}
// Ouput
// Base cons
// Derived cons
// Deleting...
// Base des
由于 Base::~Base() 不是虚拟的,当删除“派生”对象时,只会执行 Base::~Base() 。如果我们不调用 Derived::~Derived() 岂不是内存泄漏?当然,这很容易通过将 Base::~Base() 解构器标记为虚拟来解决,但是要破坏基派生类而不是派生类的场景是什么?
(我的理解是一旦基类析构函数被调用,派生对象就不再处于可用状态)
我意识到 C++ 是为效率而设计的——“只为你需要的东西付费”——所以我真的只是想了解为什么声明派生类不需要虚拟基类解构器(以避免固有内存不清理派生类的泄漏)
提前感谢您的见解。
最佳答案
执行delete derived
不一定是内存泄漏其中 derived
类型为 Base*
.因为当Base
没有虚拟析构函数,这是未定义的行为。任何事或什么事都可能发生,包括您期望发生的事情发生了。
请注意,这种情况可能发生在 unique_ptr<Base>
上。其值是从 unique_ptr<Derived>
复制而来的.所以这是一种情况,当这个特定的智能指针不那么智能时。值得牢记。
但是,shared_ptr
是安全的, 因为有 shared_ptr
原始指针保留在控制 block 中,用于删除。
关于标题中的问题,
” When would one NOT want a derived class's deconstructor to execute?
…只有当一个人根本不想破坏对象时才会这样。
我能想到的唯一示例可能是记录器对象。
关于问题文本末尾的问题,
” I'm really just looking to understand why declaring a derived class does NOT require a virtual base class deconstructor
……这是一个不同的问题。
作为一个具体的例子,使用微软的 COM 技术 IUnknown
每个 COM 类继承自的接口(interface)没有虚拟析构函数。它不需要,因为任何 COM 对象在其引用计数变为零时都会自毁。自毁代码可以访问最派生类。
关于c++ - 什么时候不希望派生类的析构函数执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36380055/