Будет ли C ++ бросить без аргументов, работающих внутри другого рама, чтобы разобрать исключение?
Вопрос
Если у меня есть код, как следующее:
try {
doSomething();
} catch (...) {
noteError();
}
void noteError() {
try {
throw;
} catch (std::exception &err) {
std::cerr << "Note known error here: " << err.what();
} catch (...) {
std::cerr << "Note unknown error here.";
}
throw;
}
Будут ли исходные исключения брошены из обоих мест внутри нижней рамы METEERROR ()?
Решение
Формулировка в стандарте (§15.1 / 2) (упор мой):
Когда исключение брошено, управление передается на Ближайший обработчик с подходящим типом (15.3); «Ближайший» означает обработчик, для которого соединение-оператор, CTOR-инициализатор или функциональный корпус После этого ключевого слова попробуйте было недавно введено потоком управления и еще не вышла.
Когда есть блок попробовать «выйти»? Согласно грамматике (§15 / 1), попробуйте заканчиваться блоками последовательность обработчиков, поэтому блок заканчивается, когда последний обработчик заканчивается. Другими словами:
try // <- start of try block
{
}
catch (whatever) // <- first handler
{
}
// ... more handlers
catch (whatever_again) // <- last handler
{
} // <- end of try block
Так что да, ваш код в порядке. При перебрешении ближайший блок TRY имеет соответствующий обработчик (а именно catch (...)
), так что обработчик введен.
Другие советы
Ваш оригинальный код был в порядке. Вы поймали различные типы исключений и называли функцией, которая будет регистрировать сообщение и Rethrow. То throw
Заявление не требуется, чтобы появиться непосредственно внутри соответствующего catch
блокировать. Если вы называете одну из этих функций «Примечание», и вы нет В настоящее время обрабатывая исключение, хотя ваша программа позвонит terminate()
.
Ваш новый код тоже в порядке. Это нормально поймать все, а затем позвонить на другую функцию, которая образуется, чтобы перейти к более конкретному обработчику. Это то Диспетчер исключений IDIOM описана в FAQ C ++. Отказ Это выглядит немного своеобразным ритроу, исключением после Диспетчерский блок закончил, но если то же самое throw
заявление произошло после noteError
вернулся (внутри оригинала catch
блок) вместо того, чтобы оно сейчас, то было бы совершенно обычным; Он продемонстрирован в стандарте, §15.1 / 6.