Будет ли деструктор базового класса вызываться, если объект генерирует исключение в конструкторе?

Будет вызван деструктор базового класса, если объект генерирует исключение в конструкторе?

Ответы

Ответ 1

Если во время построения выбрано исключение, все ранее построенные под-объекты будут правильно уничтожены. Следующая программа доказывает, что база определенно уничтожена:

struct Base
{
    ~Base()
    {
        std::cout << "destroying base\n";
    }
};

struct Derived : Base
{
    Derived()
    {
        std::cout << "throwing in derived constructor\n";
        throw "ooops...";
    }
};

int main()
{
    try
    {
        Derived x;
    }
    catch (...)
    {
        throw;
    }
}

выход:

throwing in derived constructor
destroying base

(Обратите внимание, что деструктор нативного указателя ничего не делает, поэтому мы предпочитаем RAII над необработанными указателями.)

Ответ 2

Да. Правило заключается в том, что каждый объект, конструктор которого успешно завершился, будет уничтожен при исключении. Например:

class A {
public:
    ~A() {}
};

class B : public A {
public:
    B() { throw 0; }
    ~B() {}
};

~ A(). ~ B() не вызывается;

EDIT: кроме того, предположим, что у вас есть участники:

struct A {
    A(bool t) { if(t) throw 0; }
    ~A() {}
};

struct B {
    A x, y, z;
    B() : x(false), y(true), z(false) {}
};

Что происходит: x строится, y бросает, x разрушается (но ни y, ни z).

Ответ 3

Когда генерируется исключение, деструкторы вызываются для всех (суб-) объектов, конструкторы которых были успешно запущены. Это распространяется и на члены данных и базовые классы.

Например, для этого кода

struct base {};

struct good {};

struct bad {
  bad() {throw "frxgl!";}
};

struct test : public base {
  std::string s;
  good g;
  bad b;
  test() {}
};

перед конструктором test, сначала вызывается конструктор базового класса, затем конструкторы для s, g и b. Только если они закончены успешно, выполняется конструктор для test. Когда исключение возникает при построении b, конструкторы базового класса, а также конструкторы для членов данных s и g полностью выполняются, поэтому их деструкторы запускаются. Конструктор самого test и b не был успешно запущен, поэтому их деструкторы не запускаются.

Ответ 4

Из стандартных документов, 15.3 - 11,

полностью построенные базовые классы и члены объекта должны быть уничтожены, прежде чем вводить обработчик функции try- блок конструктора или деструктора для этого объекта.