Подтвердить что ты не робот

Что "бросает"; вне блока catch делать?

Я просто наткнулся на этот код:

void somefunction()
{
   throw;
}

и мне интересно: что это значит?


Я отметил вопрос как С++ и Visual С++, потому что я не знал ответа. Ответ мог быть связан со стандартом или с специальным расширением Visual С++ или с Visual С++, игнорирующим стандарт. Вот почему я думал, что оба тега оправданы.

4b9b3361

Ответ 1

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

Если throw; выполняется, когда исключение не активно, оно вызывает terminate() (N4810, § [expr.throw]/4).

Ответ 2

Он перебрасывает текущее активное исключение. Было бы разумно назвать это (возможно, косвенно) из блока catch. Это:

#include <iostream>
using namespace std;

void f() {
    throw;
}

int main() {
    try {
        try {
            throw "foo";
        }
        catch( ... ) {
            f();
        }
    }
    catch( const char * s ) {
        cout << s << endl;
    }
}

печатает "foo".

Ответ 3

Для throw понятие "внешний" или "внутренний" блок catch определяется во время выполнения, а не во время компиляции, как вы, кажется, предполагаете. Таким образом, если во время выполнения throw выполняется во временном контексте блока catch, то throw работает так, как ожидалось. В противном случае вызывается terminate().

Фактически, если вы более подробно рассмотрите, как исключения С++ определены в спецификации языка, многие вещи о них определены во время выполнения. Иногда даже кажется, что он не похож на С++.

Ответ 4

Люди уже объяснили, что это значит, но потенциально полезно узнать, почему вы можете это увидеть. Это полезный способ создания "общего" обработчика исключений, который имеет дело с исключениями, основанными на их типе, чтобы уменьшить количество дублированного кода.

Итак, если мы возьмем пример Neil и расширим то, что может сделать f(), мы можем получить реализацию, которая делает что-то вроде моей функции LogKnownException() что я предложил в этом ответе.

Если вы работаете в команде, которая любит записывать всевозможные исключения по всему месту, вместо того, чтобы иметь огромную коллекцию блоков catch во всех этих местах (или, что еще хуже, макро), вы можете иметь простой улов блок, который выглядит следующим образом

catch(...)
{
   LogKnownException();
}  

Хотя я ожидаю, что изменил бы мой предыдущий пример LogKnownException() на тот, который просто разрешил исключения, которые он не хотел регистрировать для продолжения и продолжения необработанным способом.

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