Будет ли деструктор базового класса вызываться, если объект генерирует исключение в конструкторе?
Будет вызван деструктор базового класса, если объект генерирует исключение в конструкторе?
Ответы
Ответ 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- блок конструктора или деструктора для этого объекта.