Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  return 1; // 1 означает сбой

}

catch (...) {

  cerr << "Ой: неизвестное исключение !\n";

  keep_window_open;

  return 2; // 2 означает сбой

}

Здесь, для того чтобы перехватить все исключения, мы добавили инструкцию catch(...).

Когда исключения обоих типов (out_of_range и runtime_error) рассматриваются как разновидности одного и того же типа exception, говорят, что тип exception является базовым типом (супертипом) для них обоих. Этот исключительно полезный и мощный механизм будет описан в главах 13–16.

Снова обращаем ваше внимание на то, что значение, возвращаемое функцией main, передается системе, вызвавшей программу. Некоторые системы (такие как Unix) часто используют это значения, а другие (такие как Windows), как правило, игнорируют их. Нуль означает, что программа завершилась успешно, а ненулевое значение, возвращенное функцией main, означает какой-то сбой.

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

void error(string s1, string s2)

{

  throw runtime_error(s1+s2);

}

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

Обратите внимание на то, что использование функции error не зависит от количества ее предыдущих вызовов: функция error всегда находит ближайший раздел catch, предусмотренный для перехвата исключения runtime_error (обычно один из них размещается в функции main). Примеры использования исключений и функции error приведены в разделах 7.3. и 7.7. Если исключение осталось неперехваченным, то система выдаст сообщение об ошибке (неперехваченное исключение).

ПОПРОБУЙТЕ

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

<p id="AutBody_Root078"><strong>5.6.4. Суживающие преобразования</strong></p>

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

int x = 2.9;

char c = 1066;

  Здесь x будет равно 2, а не 2.9, поскольку переменная x имеет тип int, а такие числа не могут иметь дробных частей. Аналогично, если используется обычный набор символов ASCII, то переменная c будет равна 42 (что соответствует символу *), а не 1066, поскольку переменные типа char не могут принимать такие большие значения.

В разделе 3.9.2 показано, как защититься от такого сужения путем проверки. С помощью исключений (и шаблонов; см. раздел 19.3) можно написать функцию, проверяющую и генерирующую исключение runtime_exception, если присваивание или инициализация может привести к изменению значения. Рассмотрим пример.

int x1 = narrow_cast(2.9);    // генерирует исключение

int x2 = narrow_cast(2.0);    // OK

char c1 = narrow_cast(1066); // генерирует исключение

char c2 = narrow_cast(85);   // OK

Угловые скобки, <...>, означают то же самое, что и в выражении vector. Они используются, когда для выражения идеи возникает необходимость указать тип, а не значение. Аргументы, стоящие в угловых скобках, называют шаблонными (template arguments). Если необходимо преобразовать значение и мы не уверены, что оно поместится, то можно использовать тип narrow_cast, определенный в заголовочном файле std_lib_facilities.h и реализованный с помощью функции error. Слово cast[7] означает приведение типа и отражает роль этой операции в ситуации, когда что-то “сломалось” (по аналогии с гипсовой повязкой на сломанной ноге). Обратите внимание на то, что приведение типа не изменяет операнд, а создает новое значение, имеющее тип, указанный в угловых скобках и соответствующий операнду.

<p id="AutBody_Root079"><strong>5.7. Логические ошибки</strong></p>
Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже