Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
}
Этот фрагмент будет перехватывать все ошибки, возникающие в модулях, вызывающих функцию area(), поэтому их теперь необязательно проверять в функции framed_area(). Однако вы можете требовать большего — чтобы сообщение об ошибке было более конкретным.
Проверка аргументов в функции выглядит настолько простой, что становится непонятным, почему люди не проводят ее постоянно? Одна из причин — пренебрежение ошибками, вторая — неряшливость при написании программ, но существуют и более уважительные причины.
• Мы не можем модифицировать определение функции. Функция является частью библиотеки, поэтому ее невозможно изменить. Возможно, она будет использована другими людьми, не разделяющими вашего подхода к обработке ошибок. Возможно, она принадлежит кому-то еще, и вы не имеете доступ к ее исходному коду. Возможно, она включена в постоянно обновляющуюся библиотеку, так что если вы измените эту функцию, то будете вынуждены изменять ее в каждой новой версии.
• Вызываемая функция не знает, что делать при выявлении ошибки. Эта ситуация типична для библиотечных функций. Автор библиотеки может выявить ошибку, но только вы знаете, что в таком случае следует делать.
• Вызываемая функция не знает, откуда ее вызвали. Получив сообщение об ошибке, вы понимаете, что произошло нечто непредвиденное, но не можете знать, как именно выполняемая программа оказалась в данной точке. Иногда необходимо, чтобы сообщение было более конкретным.
• Производительность. Для небольшой функции стоимость проверки может перевесить стоимость вычисления самого результата. Например, в случае с функцией area() проверка вдвое увеличивает ее размер (т.е. удваивает количество машинных инструкций, которые необходимо выполнить, а не просто длину исходного кода). В некоторых программах этот факт может оказаться критически важным, особенно если одна и та же информация проверяется постоянно, когда функции вызывают друг друга, передавая информацию более или менее без искажений.

После обсуждения некоторых тем, связанных с этим вопросом, мы вернемся к нему в разделе 5.10.
5.5.3. Сообщения об ошибках
Рассмотрим немного иной вопрос: что делать, если вы проверили набор аргументов и обнаружили ошибку? Иногда можно вернуть сообщение “Неправильное значение”. Рассмотрим пример.
// Попросим пользователя ввести да или нет;
// Символ '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();
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Алина30 июнь 09:45 Книга интересная, как и большинство произведений Н. Свечина ( все не читала).. Не понравилось начало: Зачем постоянно... Мертвый остров - Николай Свечин
-
Гость Татьяна30 июнь 08:13 Спасибо. Интересно ... Дерзкий - Мария Зайцева
-
Лена Субботина28 июнь 18:28 Книга понравилась, понемногу втягиваешься в повествование, читается легко, сюжет интересный... Лихоимка - Надежда Храмушина