如何在异常时不从构造函数调用 base class 析构函数?

How to not call base class destructor from constructor on exception?

我有一些 classes Daughter1Daughter2 继承自 Mother:

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

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

每个女儿的共同点class删除方法都是一样的,妈妈做主。但是,他们的初始化是不一样的,所以他们在各自女儿的构造函数中:

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 析构函数中删除未初始化的指针 - 只需将指针更改为智能指针,例如std::unique_ptr 他们只会在需要时 delete 自己。

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

simply initialize them to nullptr in the mother constructor and check them before trying a deletion in the destructor

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

时可能会浪费时间

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

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

对母体进行编码,以便母体可以自行正确构造和销毁,而无需依赖任何派生的 class 的 activity。

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