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

на главную

Жанры

Программирование. Принципы и практика использования 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) {

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

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Последняя Арена 4

Греков Сергей
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 4

Маяк надежды

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

Великий перелом

Ланцов Михаил Алексеевич
2. Фрунзе
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Великий перелом

Сопротивляйся мне

Вечная Ольга
3. Порочная власть
Любовные романы:
современные любовные романы
эро литература
6.00
рейтинг книги
Сопротивляйся мне

Инквизитор Тьмы 2

Шмаков Алексей Семенович
2. Инквизитор Тьмы
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Инквизитор Тьмы 2

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

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

Бандит 2

Щепетнов Евгений Владимирович
2. Петр Синельников
Фантастика:
боевая фантастика
5.73
рейтинг книги
Бандит 2

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Падение Твердыни

Распопов Дмитрий Викторович
6. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Падение Твердыни

"Дальние горизонты. Дух". Компиляция. Книги 1-25

Усманов Хайдарали
Собрание сочинений
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Дальние горизонты. Дух. Компиляция. Книги 1-25

Ох уж этот Мин Джин Хо 2

Кронос Александр
2. Мин Джин Хо
Фантастика:
попаданцы
5.00
рейтинг книги
Ох уж этот Мин Джин Хо 2

Энфис 6

Кронос Александр
6. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 6