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

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

Ответы [ 4 ]

17 голосов
/ 21 сентября 2010

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

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 вместо необработанных указателей.)

9 голосов
/ 21 сентября 2010

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

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

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

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

РЕДАКТИРОВАТЬ: более того, предположим, что у вас есть члены:

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ни з).

5 голосов
/ 21 сентября 2010

из стандартных документов, 15,3 - 11 ,

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

5 голосов
/ 21 сентября 2010

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

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

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 не были успешно запущены, поэтому их деструкторы не запускаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...