Поймать исключение без броска

1

Я новичок в C++, и я исхожу из сценария Delphi, в котором я смог поймать исключения даже без объявления явного throw. Посмотрите здесь:

#include<iostream>
#include<exception>

int main() {

 try {

  int c;
  std::cin >> c;

 } catch(...) {

  std::cerr << "Warning!" << std::endl;
  char xz; std::cin >> xz;
  return 1;

 }

 char z; std::cin >> z;
 return 0;

}

//I return 1 because UNIX OS cares about this, a return != 0 means that Huston we have a problem

Я видел вокруг, что некоторое исключение (например, деление на ноль) автоматически не зацепилось, поэтому мне нужно создать throw сам, который наверняка будет обнаружен в моем блоке try-block.

Если вы посмотрите на код выше, когда я впервые введу 6.7 или test я должен уметь видеть на выходном warning! , но ничего. Я работаю на компьютере с Windows 10.

Я знаю, что catch(...) является общим и дает мне уверенность в защите, но почему он не поймал неправильный ввод?


Примечание. Я упомянул Delphi выше, потому что, если вы посмотрите на код ниже, я могу уловить ошибку.

try

 a := StrToInt('6.78');              //conversion error [string->double], a is int
 ShowMessage('a is ' + a.ToString);

except
 on E: Exception do

 ShowMessage('Warning! > ' + e.Message);
 //^ raises "Warning! > '6.78' is not a valid integer value."

end;

Почему я не могу произвести тот же эффект с C++? Я знаю, что это два разных языка, но сначала я бы сказал, что delphi "обрабатывает" исключения лучше. Например, он автоматически ловит деление на ноль (см. Ниже), в то время как C++ не работает.

//this raises the "Division by zero" error.
a := 8 div StrToInt('0');

Заключение. Итак, вопросы: я правильно объявляю C++ try-catch? Всегда ли я должен использовать throw чтобы быть уверенным, что ошибка будет поймана или я могу опустить это несколько раз?

  • 0
    Catch - неправильный глагол, а 2-й из пойман, а не пойман. (поймать поймали поймали)
  • 0
    Исключения в Delphi работают примерно так же, как и в C ++. Вы не можете поймать то, что не брошено. Кто-то должен бросить, будь то вы или библиотеки, в которые вы звоните. Такие функции, как StrToInt() имеют явные операторы raise которые генерируют исключения, когда они сталкиваются с неверными входными данными Delphi RTL также реагирует на сгенерированные системой исключения (нарушение доступа, деление на ноль и т. Д.) И преобразует их в исключения в стиле Delphi. Вот почему вы можете ловить такие вещи, как EAccessViolation , EDivByZero и т. Д. C ++ не выполняет такое преобразование, но существуют сторонние библиотеки, которые делают это.
Теги:
exception
try-catch

2 ответа

8
Лучший ответ

std::cin не будет бросать, когда пользователь вводит недопустимый тип.

Предполагая, что С++ 11 и выше, поведение выглядит следующим образом:

Если извлечение завершается неудачно, нуль записывается в значение и устанавливается битбита. Если извлечения приводит к слишком большому или слишком маленькому значению, чтобы соответствовать значению, записывается std :: numeric_limits :: max() или std :: numeric_limits :: min() и устанавливается флаг failbit.

из std::basic_istream::operator>>.

Чтобы проверить, недействителен ли вход, вы должны сделать следующее:

#include <cstdint>
#include <iostream>

std::int32_t main()
{
    std::int32_t example;
    std::cin >> example;

    if (std::cin.fail())
    {
        std::cout << "Invalid input" << std::endl;
    }
}

Или вы также можете сделать это следующим образом:

#include <cstdint>
#include <iostream>

std::int32_t main()
{
    std::int32_t example;

    if (!(std::cin >> example))
    {
        std::cout << "Invalid input" << std::endl;
    }
}
  • 0
    Вместо этого вы также можете использовать операторы преобразования bool , например: if (!(std::cin >> example)) .
9

Как указано в документации, вам нужно установить маску исключений для std::cin чтобы заставить ее сбрасывать std::ios_base::failure:

#include <iostream>

int main() {
    std::cin.exceptions( std::ios::failbit );
    try {
       int i = 0;
       std::cin >> i;
       std::cout << "i=" << i << std::endl;
    }
    catch(...) {
        std::cerr << "error!" << std::endl;
    }
    return 0;
}

живой пример

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню