Приведет ли исключение в блоке улова к двум исключениям, находящимся в полете?

Рассмотрим следующий код C ++:

class MyException {};

void someFunction()
{
try
{
/// ... code that may throw
}
catch(std::exception& e )
{
throw MyException();
}
}

Вопрос

Поглощено ли исключение e в начале блока захвата или в конце блока захвата?

Во втором случае создание нового исключения привело бы к двум исключениям в полете, а это не то, что я хочу. Я хочу поглотить исключение std :: и запустить один из моих собственных типов.

4

Решение

Вот как это нужно делать. throw myException() может произойти, только если первое исключение было обнаружено и, следовательно, больше не «в полете».

Этот шаблон проектирования довольно распространен для «перевода» сообщений об ошибках, поступающих из другой библиотеки, которую использует ваш код, в ошибку, к которой пользователь вашего кода может лучше относиться.

В качестве альтернативы, если вы хотите сделать больше, чем просто throw (скажем, вы хотите провести некоторую очистку ресурсов — хотя это действительно должно быть сделано с помощью RAII, то есть от деструкторов), тогда вы можете просто сбросить исходное исключение через

try
{
// ... code that may throw
}
catch(...) // catches anything
{
// ... code that runs before rethrowing
throw;    // rethrows the original catch
}
3

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

просто throw; оператора достаточно в блоке catch, чтобы перебросить то же исключение в более высоком контексте.
Это бросает то же самое исключение снова. Новое исключение не генерируется. Так что не бойся 🙂

Если вы хотите перехватить исключение типа A, а затем выбросить исключение типа B, то способ, которым вы это сделали, является абсолютно правильным.
В этом случае старое исключение (тип A) перехватывается (поглощается), и только новое исключение (тип B) выбрасывается в более высокий контекст. Итак, снова не бойся 🙂

1