【问题标题】:How to not call base class destructor from constructor on exception?如何在异常时不从构造函数调用基类析构函数?
【发布时间】:2015-12-22 19:42:38
【问题描述】:

我有一些类Daughter1Daughter2 继承自Mother

class   Mother
{
public:
    Mother(); // Empty constructor.
    virtual ~Mother(); // Delete common daughter's stuff.

protected:
    // Common stuff of each daughter.
};

每个子类的通用东西删除方法都是一样的,所以妈妈负责。但是它们的初始化是不一样的,所以它们在各自女儿的构造函数中:

class   Daughter1 : public Mother
{
public:
    Daughter1(); // Initialize mother's stuff
    ~Daughter1();
};

class   Daughter2 : public Mother
{
public:
    Daughter2(); // Initialize mother's stuff in a different way than Daughter1
    ~Daughter2();
};

问题是:有时,子构造函数可能无法加载其内容并引发异常。当我这样声明女儿时:

Daughter1   daughter;

并且构造函数抛出异常,它调用母亲的析构函数,它试图在没有初始化的情况下删除它的东西,这不可避免地导致分段错误。

避免这种麻烦的最好方法是什么?


我的大部分东西都是由指针组成的,所以我知道我可以在母构造函数中简单地将它们初始化为 nullptr 并在尝试在析构函数中删除之前检查它们,但它只适用于指针,我正在寻找寻求全球解决方案。

【问题讨论】:

  • 如果不了解 Mother::Mother 的作用,就很难提出建设性的建议。
  • @RSahu 母构造函数为空。我添加了精度。

标签: c++ c++11 exception constructor destructor


【解决方案1】:

您不应该在 Mother 析构函数中删除未初始化的指针 - 只需将指针更改为智能指针,例如std::unique_ptr,他们只会在需要时delete

更一般地说,~Mother 仅在 Mother 基类完成构造时调用,然后每个成员变量应处于任何析构函数都可以安全运行的状态。对于像doubleint 这样的类型,没有什么可以破坏的,所以不需要做任何事情。使用智能指针而不是原始指针,或标准容器/std::string 而不是您自己的黑客。更一般地,寻找或制作遵循RAII 原则的类,以确保它们能够正确地自我清理。

只需在母构造函数中将它们初始化为nullptr,并在尝试在析构函数中删除之前检查它们

FWIW,没有必要在 delete...delete 之前检查它们 nullptr 是(安全)无操作。换句话说,您添加的任何检查都是多余的,并且当指针不是 nullptr 时可能会浪费时间。

【讨论】:

  • 但是最终将它们初始化为 nullptr 并仅当它们不再是 nullptr 时才将它们删除?
  • @Aracthor:是的,这几乎是一样的,除了它是类型固有的,不需要在构造函数和析构函数之间进行协调,你更容易忘记这样做偶尔对某些成员进行初始化和/或删除....
【解决方案2】:

Mother 的东西应该由 Mother 的构造函数初始化,而不是 Daughter 的。将任何所需的初始化参数作为构造函数参数传递给 Mother 的构造函数,而不是(我假设你正在这样做)在 Daughter 构造函数中使用赋值语句。

对 Mother 进行编码,以便 Mother 可以自行正确构建和销毁,而无需依赖任何派生类的活动。

Daughter1 daughter(); 声明了一个函数,没有调用构造函数。

【讨论】:

    【解决方案3】:

    另一种可能的解决方案是使用静态方法来创建 Daughter 对象(如 here)而不是真正的构造函数。在这种情况下,您可以使构造函数非常轻量且不会抛出,只需将所有复杂的逻辑都放入这些静态方法中。

    【讨论】:

      猜你喜欢
      • 2015-07-18
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 2017-02-08
      • 2018-07-21
      • 2018-05-25
      相关资源
      最近更新 更多