Я просто споткнулся этот код:
void somefunction()
{
throw;
}
и интересно:что это значит?
Я отметил вопрос как C++ и Visual C++, потому что я не знал ответ. Ответ, возможно, был связан со стандартом или со специальным расширением Visual C++ или к Visual C++, игнорирующему стандарт. Вот почему я думал, что оба тега выравниваются по ширине.
Вероятно, предполагается, что somefunction ()
всегда вызывается только из некоторого блока catch
. В этом случае было бы активным исключение при выполнении throw ;
, и в этом случае текущее исключение генерируется повторно, чтобы его перехватил следующий внешний обработчик, который может обработать этот тип исключения.
Если throw;
выполняется, когда исключение неактивно, он вызывает terminate ()
(N4810, § [expr.throw] / 4).
Для throw
концепция «внешнего» или «внутреннего» блока catch определяется в терминах времени выполнения, а не в терминах времени компиляции, как вы, кажется, предполагаете. Итак, если во время выполнения throw
выполняется в контексте времени выполнения блока catch
, то throw
работает должным образом. В противном случае вызывается terminate ()
.
На самом деле, если вы внимательно посмотрите на то, как исключения C ++ определены в спецификации языка, многое в них определяется в терминах времени выполнения. Иногда это даже не похоже на C ++.
Люди уже объяснили, что это означает, но это потенциально полезно для знаю, почему вы можете это увидеть. Это полезный способ создания «универсального» обработчика исключений, который обрабатывает исключения в зависимости от их типа, чтобы уменьшить количество дублированного кода.
Итак, если мы возьмем пример Нила и расширим то, что может делать f ()
, мы можем получить реализацию, которая делает что-то вроде моего LogKnownException ()
функция, которую я предложил в ответе .
Если вы работаете в команде, которая любит регистрировать всевозможные исключения повсюду, то вместо того, чтобы иметь огромную коллекцию блоков catch во всех этих местах (или, что еще хуже, макрос), вы можете иметь простой улов блок, который выглядит следующим образом
catch(...)
{
LogKnownException();
}
Хотя я ожидаю, что я изменил свой предыдущий пример LogKnownException ()
на тот, который просто разрешал исключения, которые он не хотел регистрировать для распространения и продолжения в необработанная мода.
Я не утверждаю, что это обязательно хорошо, просто указываю, что именно здесь вы, вероятно, увидите использованную конструкцию.
Он повторно генерирует текущее активное исключение. Было бы разумно вызывать его (возможно, косвенно) из блока 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».