c++ - 什么时候不希望派生类的析构函数执行?

标签 c++ inheritance

考虑以下示例:

#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/

相关文章:

c++ - ffmpeg avcodec_open2 更改了 AVCodecContext 中的音频格式

C++ 跨边界使用 std::vector

c++ - 奇怪的 Adob​​e Alchemy 编译器失败

java - Java 父类未调用 Scala 子类构造函数

java - Java的四级继承

java - 下面的java代码有什么问题吗?

c++ - 返回类型协变

c++ - std::string 到 BYTE[]

c++ - 仅将纪元字符串保存到 mysql 日期时间年/月/日但没有小时分钟秒

java - 视觉范例,不能在 DCD 上使用持久性继承