ловя двойное исключение

У меня есть следующий код:

#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;
}

Теперь, прежде чем сформулировать вопрос, я хотел бы отметить, что этот код является плохой практикой (например, создание исключения из конструктора приведет к тому, что объект не будет полностью создан, поэтому деструктор не будет вызван, и это может вызвать утечки памяти или другие проблемы).

Теперь, порядок основных заключается в следующем:

  1. печать "Entering try...catch block",

  2. призвание Aконструктор, печать "A::A()"

  3. призвание Bконструктор, печать "B::B()"и выбрасывает исключение.

  4. Исключение было брошено, и линия "Exiting try...catch block" не будет напечатан. Блок вышел, поэтому Aдеструктор называется.

  5. Aдеструктор печатает "A::~A()" и бросает еще одно исключение.

Второе исключение (в 5) приводит к тому, что main вызывает исключение, прежде чем войти в catch блок.

У меня такой вопрос — есть ли способ поймать второе исключение в основном, не меняя классов A,B?

Я пытался окружить как целое try-catch блок и внутри catch блокировать с другим try-catch блок, но это не сработало.

Благодарю.

2

Решение

От cppreference.com:

Как и любая другая функция, деструктор может завершиться, выдав исключение […], однако, если этот деструктор вызван во время разматывания стека, std::terminate называется вместо.

Итак, попытка выбросить исключение из ~A() не приводит к выбрасыванию второго исключения; это приводит к завершению программы. Если вам нужно «поймать» это «второе исключение», вам нужно будет помешать обработчик завершения. Или вы можете найти способ не создавать исключение в деструкторе. Продолжая cppreference.com:

Хотя std::uncaught_exception иногда может использоваться для обнаружения процесса раскручивания стека, обычно считается плохой практикой разрешать любому деструктору завершать работу, выдавая исключение.

5

Другие решения

Других решений пока нет …