Ответ 1
Да. Исключение активно до тех пор, пока оно не поймается, когда оно станет неактивным. Но он живет до тех пор, пока не закончится область действия обработчика. Из стандарта основное внимание уделяется:
§15.1/4: память для временной копии генерируемого исключения распределяется неопределенным способом, за исключением случаев, указанных в 3.7.4.1. Временное сохранение сохраняется до тех пор, пока выполняется обработчик для этого исключения.
То есть:
catch(...)
{ // <--
/* ... */
} // <--
Между этими стрелками вы можете повторно выбросить исключение. Только тогда, когда заканчивается область обработчиков, исключение перестает существовать.
Фактически, в §15.1/6 приведенный пример почти такой же, как ваш код:
try {
// ...
}
catch (...) { // catch all exceptions
// respond (partially) to exception <-- ! :D
throw; //pass the exception to some
// other handler
}
Имейте в виду, если вы throw
без активного исключения, будет вызван terminate
. Это не может быть для вас, находясь в обработчике.
Если doSomethingElse()
выбрасывает и исключение не имеет соответствующего обработчика, потому что исходное исключение считается обработанным, новое исключение заменит его. (Как будто он только что выброшен, начинается раскручивание стека и т.д.)
То есть:
void doSomethingElse(void)
{
try
{
throw "this is fine";
}
catch(...)
{
// the previous exception dies, back to
// using the original exception
}
try
{
// rethrow the exception that was
// active when doSomethingElse was called
throw;
}
catch (...)
{
throw; // and let it go again
}
throw "this replaces the old exception";
// this new one takes over, begins stack unwinding
// leaves the catch scope, old exception is done living,
// and now back to normal exception stuff
}
try
{
throw "original exception";
}
catch (...)
{
doSomethingElse();
throw; // this won't actually be reached,
// the new exception has begun propagating
}
Конечно, если ничего не будет сделано, throw;
будет достигнуто, и вы бросите свое пойманное исключение, как ожидалось.