Исключение исключений

Почему следующее не обрабатывает исключение, которое было повторно установлено? Я пробовал все комбинации, но ни один из них не показывал результат в последнем catch, поэтому я смущен!

Derived D;

try {
       throw D;
} catch ( const Derived &d) {
       throw;
} catch (const Base &b) {
      cout << "caught!" << endl;
}

Derived D;

try {
    throw D;
} catch ( const Derived d) {
    throw;
} catch (const Base b) {
    cout << "caught!" << endl;
}

Derived D;

try {
    throw D;
} catch ( const Derived d) {
    throw;
} catch (const Base &b) {
    cout << "caught!" << endl;
}

Derived D;

try {
    throw D;
} catch ( const Derived &d) {
    throw;
} catch (const Base b) {
    cout << "caught!" << endl;
}

Ответ 1

Повторный бросок не обрабатывается одним и тем же блоком try-catch. Он перешел в область вызова.

В [except.throw] (формулировка 2003):

Выражение-выражение без операнда переводит обрабатываемое исключение.

и

Когда генерируется исключение, управление передается ближайшему обработчику с соответствующим типом (15.3); "ближайший" означает обработчик, для которого выполняется составной оператор, ctor-initializer или function-body ключевое слово try было недавно введено потоком управления и еще не вышло.

Ваш блок try вышел, поэтому его обработчики не являются кандидатами. Таким образом, ни один из блоков catch в вашем коде не может обрабатывать повторный бросок.

По общему признанию, это довольно запутанная формулировка.

Ответ 2

Исключенное исключение должно быть уловлено каким-либо другим блоком try..catch, а не обработчиком catch того же блока try. См. Этот пример:

using namespace std;
class Base
{
public:
    virtual ~Base(){}
};

class Derived : public Base
{
};

void f()
{
    try
    {
        throw Derived();
    }
    catch(Derived& ex)
    {
        cout<<"Caught in f\n";
        throw;
    }

}

int main()
{
    try
    {
        f();
    }
    catch(Base& b)
    {
        cout<<"Caught in main\n";
    }

    return 0;
}

:

Пойманный в f

Пойманный в основном

Ответ 3

Это должно работать:

Derived D;


try{

    try {
        throw D;
    } catch ( const Derived &d) {
        throw;
    } catch (const Base &b) {
        cout << "caught!" << endl;
    }

} catch (const Base &b) {
    cout << "caught here!" << endl;
}

Как и все сказанное, rethrow выведет одно и то же исключение из блока catch.