Выброс исключения без параметров

147
16 июня 2019, 02:00

Читаю статью по исключениям и решил скопировать код оттуда. Вот код:

int main(int argc, char* argv[]){
try {
    throw;
}
catch (...) {
    cout << "exception\n";
    return 1;
}
cout << "No exeption\n";
return 0;
}

В статье написано что блок catch должен поймать его, но этого не происходит. Почему? Использую msvs 2017. И ещё,

int main(int argc, char* argv[]){
int x = 0;
try {
    cout << 2 / x;
}
catch (...) {
    cout << "exception\n";
    return 1;
}

Тут тоже не ловится исключение типа "Деление на 0". Почему?

Answer 1

Да, есть такой вариант.

  • Если указан в теле try, то работает как terminate, то есть с "мясом" прерывает выполнение текущего приложения (порты и файлы не закрываются, ресурсы не освобождаются).
  • Если находится внутри какого-то catch(), то есть мы уже поймали какое-то типизированное исключение, то это просто короткая запись для "перебрасывания" того же исключения дальше (выше по стеку).
Answer 2

Оператор throw без параметров может использовать только во время обработки уже пойманного исключения. В остальных случаях попытка выполнения оператора throw без параметра приведет к немедленному вызову std::terminate.

http://eel.is/c++draft/expr.throw#4

4 If no exception is presently being handled, evaluating a throw-expression with no operand calls std​::​​terminate().

Обратите внимание: "во время обработки уже пойманного исключения" - это характеристика времени выполнения. То есть такой throw не обязан явно синтаксически располагаться на территории try-блока. Такой throw только должен выполняться во время, когда какой-то try-блок активен.

В языке С++ нет никакого исключения "деление на 0". Деление на 0 приводит к неопределенному поведению, а не к выбросу исключения. Исключения в С++ выбрасываются либо явно, при помощи throw, либо неявно изнутри конструкций языка и стандартной библиотеки в специально оговоренных случаях. Деление на 0 таким случаем не является.

Answer 3

throw без параметров действительно может быть использован. Он предназначен для того, чтобы перебросить исключение в вышестоящий try-catch блок.

void foo()
{
   throw 10;
}
void buz()
{
   try
   {
      foo();
   }
   catch(...)
   {
      std::cout << "exception in buz()\n";
      throw;
   }
}
int main()
{
    try
    {
        buz();
    }
    catch(int er)
    {
        std::cout << "exception in main: " << er << "\n";
    }
    return 0;
}

Если на момент использования throw; ни одно исключение не обрабатывается (не является активным), тогда такое выражение будет вызывать std::terminate.

Посмотреть

throw

Answer 4

С сайта cplusplus.com:

It is also possible to nest try-catch blocks within more external try blocks. In these cases, we have the possibility that an internal catch block forwards the exception to its external level. This is done with the expression throw; with no arguments. For example:

try {
    try {
        // code here
    }
    catch (int n) {
        throw;
    }
}
catch (...) {
    cout << "Exception occurred";
}

Т.к. сообщество рускоязычное, суть примерно такая:

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

Это подтверждает то, что сказал AR Hovsepyan в комментарии под вопросом:

Но у вас не брошено нигде исключение, а попытка бросить его заново

READ ALSO
MessageBox C++. Проблема с выводом строки

MessageBox C++. Проблема с выводом строки

Мне нужно в MessageBox запихнуть stringНа выходе я получаю не нужную строку, а набор китайских иероглифов

122
Количество счастливых чисел

Количество счастливых чисел

Ну вообще не понимаю как решить данную задачу (наверное она на метод включения-исключения)

117
Скопировать все файлы [закрыт]

Скопировать все файлы [закрыт]

Как можно скопировать все файлы, имена которых начинается с "stat" (есть примерно 500 файлов типа stat1txt stat2

165