Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

// ...

}

Вы заметили ошибку? Такие ошибки трудно выявить, так как сам код является правильным: ошибка заключается в том, что программист не включил в него проверку.

ПОПРОБУЙТЕ

Выполните эту программу при разных значениях. Выведите на печать значения переменных

area1
,
area2
,
area3
и
ratio
. Вставьте в программу больше проверок разных ошибок. Вы уверены, что перехватите все ошибки? Это вопрос без подвоха; в данном конкретном примере можно ввести правильный аргумент и перехватить все возможные ошибки.

Существует другой способ решить описанную проблему: использовать исключения (exceptions).

5.6. Исключения

Как и в большинстве языков программирования, в языке С++ существует механизм обработки ошибок: исключения. Основная идея этого понятия заключается в отделении выявления ошибки (это можно сделать в вызываемой функции) от ее обработки (это можно сделать в вызывающей функции), чтобы гарантировать, что ни одна выявленная ошибка не останется необработанной. Иначе говоря, исключения создают механизм, позволяющий сочетать наилучшие подходы к обработке ошибок, исследованные нами до сих пор. Какой бы легкой ни была обработка ошибок, исключения сделают ее еще легче.

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

return
как обычно, а генерирует исключение с помощью оператора
throw
, показывая, что произошло нечто неправильное.

Любая функция, прямо или косвенно вызывающая данную функцию, может перехватить созданное исключение с помощью оператора

catch
, т.е. указать, что следует делать, если вызываемый код использовал оператор
throw
. Функция расставляет ловушки для исключения с помощью блока
try
(мы опишем его в следующих разделах), перечисляя виды исключений, которые она хочет обработать в своих разделах
catch
блока
try
. Если ни одна из вызывающих функций не перехватила исключение, то программа прекращает работу.

Мы еще вернемся к исключениям позже (в главе 19), чтобы использовать их немного более сложным способом.

5.6.1. Неправильные аргументы

Рассмотрим вариант функции

area
, использующий исключения.

class Bad_area { }; // Тип, созданный специально для сообщений

// об ошибках,

// возникших в функции area

// Вычисляет площадь прямоугольника;

// при неправильном аргументе генерирует исключение Bad_area

int area(int length, int width)

{

if (length<=0 || width<=0) throw Bad_area;

return length*width;

}

Иначе говоря, если аргументы правильные, то программа всегда возвращает площадь прямоугольника, а если нет, то выходим из функции

area
с помощью оператора
throw
, надеясь найти ответ в одном из разделов
catch
.
Bad_area
— это новый тип, предназначенный исключительно для генерирования исключений в функции
area
, так, чтобы один из разделов
catch
распознал его как исключение, сгенерированное функцией
area
. Типы, определенные пользователями (классы и перечисления), обсуждаются в главе 9. Обозначение
Bad_area
означает “Создать объект типа Bad_area”, а выражение
throw Bad_area
означает “Создать объект типа
Bad_area
и передать его (
throw
) дальше”.

Теперь функцию можно написать так:

int main

try {

int x = –1;

int y = 2;

int z = 4;

// ...

int area1 = area(x,y);

int area2 = framed_area(1,z);

int area3 = framed_area(y,z);

double ratio = area1/area3;

}

catch (Bad_area) {

cout << "Ой! Неправильный аргумент функции area\n";

}

Во-первых, этот фрагмент программы обрабатывает все вызовы функции

area
как вызов из модуля
main
, так и два вызова из функции
framed_area
. Во-вторых, обработка ошибки четко отделена от ее выявления: функция
main
ничего не знает о том, какая функция выполнила инструкцию
throw Bad_area
, а функция
area
ничего не знает о том, какая функция (если такая существует) должна перехватывать исключения
Bad_area
, которые она генерирует. Это разделение особенно важно в крупных программах, написанных с помощью многочисленных библиотек. В таких программах ни один человек не может обработать ошибку, просто поместив некоторый код в нужное место, поскольку никто не может модифицировать код одновременно в приложении и во всех библиотеках.

5.6.2. Ошибки, связанные с диапазоном

Большинство реальных программ работает с наборами данных. Иначе говоря, они используют разнообразные таблицы, списки и другие структуры данных. В контексте языка С++ наборы данных часто называют контейнерами (containers). Наиболее часто используемым контейнером стандартной библиотеки является тип vector, введенный в разделе 4.6.

Объект типа

vector
хранит определенное количество элементов, которое можно узнать с помощью его функции-члена
size
. Что произойдет, если мы попытаемся использовать элемент с индексом, не принадлежащим допустимому диапазону
[0:v.size]
? Обычное обозначение
[low:high]
означает, что индексы могут принимать значения от low до
high-1
, т.е. включая нижнюю границу, но исключая верхнюю.

  • Читать дальше
  • 1
  • ...
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: