Исключение заставит стек развернуться до точки, где исключение будет правильно перехвачено. Это означает, что любые объекты, созданные в области видимости до возникновения исключения, будут уничтожены, включая объекты базового класса, как в этом примере.
Попробуйте это:
#include <iostream>
class A
{
public:
A() { std::cout << "A::A()\n";}
~A() {std::cout << "A::~A()\n";}
};
class B : public A
{
public:
B()
{
std::cout << "B::B()\n";
throw 'c';
}
// note: a popular point of confusion --
// in this example, this object's destructor
// WILL NOT BE CALLED!
~B()
{
std::cout << "B::~B()\n";
}
};
int main()
{
try
{
B b;
}
catch(...)
{
std::cout << "Fin\n";
}
return 0;
}
Вывод должен быть: (примечание B::~B()
не вызывается)
A::A()
B::B()
A::~A()
Fin
Вызов деструктора вручную, как вы показали в своем вопросе, будет безопасным, если вы не пытаетесь освободить ресурсы, которые вы еще не выделили. Лучше обернуть эти ресурсы в некоторый тип контейнера RAII
(std::auto_ptr
, boost::shared_ptr
и т. Д.), Чтобы избежать необходимости вызова деструктора.
Mooing Duck предоставил очень хорошую иллюстрацию того, как работает раскрутка стека, когда в конструкторе выдается исключение: