Этой простой обработки ошибки нам будет достаточно, пока ситуация не усложнится и потребуется придумать более изощренный способ исправить ситуацию.
Обратите внимание на то, что использование функции
error
не зависит от количества ее предыдущих вызовов: функция
error
всегда находит ближайший раздел
catch
, предусмотренный для перехвата исключения
runtime_error
(обычно
один из них размещается в функции
main
). Примеры использования исключений и функции
error
приведены в разделах 7.3. и 7.7. Если исключение осталось неперехваченным, то система выдаст сообщение об ошибке (неперехваченное исключение).
ПОПРОБУЙТЕ
Для того чтобы увидеть неперехваченное исключение, запустите небольшую программу, в которой функция
error
не перехватывает никаких исключений.
5.6.4. Суживающие преобразования
В разделе 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<int>(2.9); // генерирует исключение
. Они используются, когда для выражения идеи возникает необходимость указать тип, а не значение. Аргументы, стоящие в угловых скобках, называют шаблонными (template arguments). Если необходимо преобразовать значение и мы не уверены, что оно поместится, то можно использовать тип
narrow_cast
, определенный в заголовочном файле
std_lib_facilities.h
и реализованный с помощью функции
error
. Слово
cast
[7] означает приведение типа и отражает роль этой операции в ситуации, когда что-то “сломалось” (по аналогии с гипсовой повязкой на сломанной ноге). Обратите внимание на то, что приведение типа не изменяет операнд, а создает
новое значение, имеющее тип, указанный в угловых скобках и соответствующий операнду.
7
Буквально гипсовая повязка. — Примеч. ред.
5.7. Логические ошибки
После устранения ошибок, выявленных компилятором и редактором связей, программу выполняют. Как правило, после этого программа либо ничего не выдает на печать, либо выводит неправильные результаты. Это может происходить по многим причинам. Возможно, вы просто неправильно поняли логику программы; написали не то, что намеревались; сделали глупую ошибку в какой-нибудь инструкции
if
или что-нибудь еще. Логические ошибки обычно труднее всего находить и исправлять, поскольку на этой стадии компьютер делает только то, что вы сами ему приказали. Теперь ваша задача выяснить, почему он делает не то, что вы хотели. В принципе компьютер — это очень быстро действующий идиот. Он просто покорно делает в точности то, что вы ему сказали.
Попробуем проиллюстрировать сказанное на простом примере. Рассмотрим программу-код для поиска минимальной, максимальной и средней температуры.
int main
{
vector<double> temps; // температуры
double temp = 0;
double sum = 0;
double high_temp = 0;
double low_temp = 0;
while (cin>>temp) // считываем и записываем в вектор temps
Мы проверили эту программу, введя почасовые данные о температуре в центре Люббока, штат Техас (Lubbock, Texas) 16 февраля 2005 года (в штате Техас по-прежнему используется шкала Фаренгейта).
Наивный программист может прийти к выводу, что программа работает просто отлично. Безответственный программист продаст ее заказчику. Благоразумный программист проверит программу еще раз. Для этого мы ввели данные, полученные 23 июля 2005 года.