У меня есть следующий код:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A::A()" << endl;}
~A() { cout << "A::~A()" << endl; throw "A::exception";}
};
class B {
public:
B() { cout << "B::B()" << endl; throw "B::exception";}
~B() { cout << "B::~B()";}
};
int main() {
try {
cout << "Entering try...catch block" << endl;
A objectA;
B objectB;
cout << "Exiting try...catch block" << endl;
} catch (char const * ex) {
cout << ex << endl;
}
return 0;
}
Теперь, прежде чем сформулировать вопрос, я хотел бы отметить, что этот код является плохой практикой (например, создание исключения из конструктора приведет к тому, что объект не будет полностью создан, поэтому деструктор не будет вызван, и это может вызвать утечки памяти или другие проблемы).
Теперь, порядок основных заключается в следующем:
печать "Entering try...catch block"
,
призвание A
конструктор, печать "A::A()"
призвание B
конструктор, печать "B::B()"
и выбрасывает исключение.
Исключение было брошено, и линия "Exiting try...catch block"
не будет напечатан. Блок вышел, поэтому A
деструктор называется.
A
деструктор печатает "A::~A()"
и бросает еще одно исключение.
Второе исключение (в 5) приводит к тому, что main вызывает исключение, прежде чем войти в catch
блок.
У меня такой вопрос — есть ли способ поймать второе исключение в основном, не меняя классов A
,B
?
Я пытался окружить как целое try-catch
блок и внутри catch
блокировать с другим try-catch
блок, но это не сработало.
Благодарю.
От cppreference.com:
Как и любая другая функция, деструктор может завершиться, выдав исключение […], однако, если этот деструктор вызван во время разматывания стека,
std::terminate
называется вместо.
Итак, попытка выбросить исключение из ~A()
не приводит к выбрасыванию второго исключения; это приводит к завершению программы. Если вам нужно «поймать» это «второе исключение», вам нужно будет помешать обработчик завершения. Или вы можете найти способ не создавать исключение в деструкторе. Продолжая cppreference.com:
Хотя
std::uncaught_exception
иногда может использоваться для обнаружения процесса раскручивания стека, обычно считается плохой практикой разрешать любому деструктору завершать работу, выдавая исключение.
Других решений пока нет …