- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
}
Этот фрагмент будет перехватывать все ошибки, возникающие в модулях, вызывающих функцию 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();

