Чтение онлайн

на главную - закладки

Жанры

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

// Попросим пользователя ввести да или нет;

// Символ 'b' означает неверный ответ (т.е. ни да ни нет)

char ask_user(string question)

{

cout << question << "? (да или нет)\n";

string answer = " ";

cin >> answer;

if (answer =="y" || answer=="yes") return 'y';

if (answer =="n" || answer=="no") return 'n';

return 'b'; // 'b', если "ответ
неверный"

}

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

// возвращает –1, если аргумент неправильный

int area(int length, int width)

{

if (length<=0 || width <=0) return –1;

return length*width;

}

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

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

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

• Многие функции не имеют возможность возвращать дополнительные значения, чтобы сообщить об ошибке. Например, функция, считывающая целое число из потока ввода (скажем, оператор

>>
потока
cin
), может возвращать любое целое число, поэтому использовать целое число в качестве индикатора ошибки бессмысленно.

Вторая ситуация, в которой проверка в вызывающем модуле не выполняется, может легко привести к неожиданностям

Рассмотрим пример.

int f(int x, int y, int z)

{

int area1 = area(x,y);

if (area1<=0) error("Неположительная площадь");

int area2 = framed_area(1,z);

int area3 = framed_area(y,z);

double ratio = double(area1)/area3;

// ...

}

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

ПОПРОБУЙТЕ

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

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) {

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

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Хозяйка дома в «Гиблых Пределах»

Нова Юлия
Любовные романы:
любовно-фантастические романы
5.75
рейтинг книги
Хозяйка дома в «Гиблых Пределах»

Неудержимый. Книга XVI

Боярский Андрей
16. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XVI

Стражи душ

Кас Маркус
4. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Стражи душ

Отмороженный 9.0

Гарцевич Евгений Александрович
9. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 9.0

Последний Паладин. Том 4

Саваровский Роман
4. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 4

Ливонская партия

Ланцов Михаил Алексеевич
3. Иван Московский
Фантастика:
альтернативная история
5.00
рейтинг книги
Ливонская партия

Возвышение Меркурия. Книга 13

Кронос Александр
13. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 13

Ваантан

Кораблев Родион
10. Другая сторона
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Ваантан

Не отпускаю

Шагаева Наталья
Любовные романы:
современные любовные романы
эро литература
8.44
рейтинг книги
Не отпускаю

Мастер Разума V

Кронос Александр
5. Мастер Разума
Фантастика:
городское фэнтези
попаданцы
5.00
рейтинг книги
Мастер Разума V

Действуй, дядя Доктор!

Юнина Наталья
Любовные романы:
короткие любовные романы
6.83
рейтинг книги
Действуй, дядя Доктор!

Шведский стол

Ланцов Михаил Алексеевич
3. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Шведский стол

В теле пацана 4

Павлов Игорь Васильевич
4. Великое плато Вита
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
В теле пацана 4