|
Программирование >> Структурное программирование
выбрасывает исключение). При этом нет никаких гарантий, что где-то вне этой функции существует нечто (обработчик исключения), запускающее обработку именно этого вида исключения. Если существует, то исключение будет перехвачено и обработано. Если же для этого специфического вида исключения не имеется никакого обработчика, программа завершается. Программист заключает в так называемый блок try (блок испытания) тот код, который может сгенерировать ошибку, возбуждающую исключение. Следом за блоком try записывается один или более блоков catch (блоки перехвата). Каждый блок catch определяет тип исключений, которые он может перехватывать и обрабатывать. Каждый блок catch содержит программу обработки - обработчик исключения. Если исключительная ситуация соответствует типу параметра в одном из блоков catch, выполняется код этого блока. В противном случае вызывается функция terminate (завершение), которая по умолчанию вызывает функцию abort (аварийное завершение работы). Программное управление при генерации исключения осуществляет выход из блока try и последовательный поиск в блоках catch соответствующего обработчика (мы скоро обсудим то, что делает обработчик соответствующим ). Если никакие исключения в блоке try не генерируются, обработчики исключений для такого блока пропускаются и программа продолжает выполняться с операторов, следующих за последним блоком catch. Мы можем указать те исключения, которые могут генерироваться конкретной функцией. В частном случае мы можем определить, что функция вообще не генерирует никаких исключений. Исключение генерируется в функции блока try или в функции, вызываемой непосредственно или косвенно из блока try. Точка, в которой выполняется генерация (throw), называется точкой генерации. Этот термин также используется для описания самого выражения throw. После того, как исключение сгенерировано, управление не может возвратиться в точку генерации. Когда возникает исключение, можно передать информацию из точки генерации обработчику этого исключения. Это информация о типе самого сгенерированного объекта или информация, помещенная в этот объект. Генерируемый объект обычно является строкой символов (для сообщения об ошибке) или объектом классом. Генерируемый объект передает информацию обработчику исключения. Замечание по технике программирования 13.4 Ключевым моментом в стиле обработки исключений в С++ является то, что часть программы или сиаемы, которая будет обрабатывать исключение, может бьпь совершенно отделена и удалена от той части программы, которая обнаружила и возбудила исключение. 13.5. Простой пример обработки исключений: деление на нуль Давайте теперь рассмотрим простой пример обработки исключений. Программа на рис. 13.1 использует операторы try, throw и catch, чтобы обнаружить, указать и обработать исключение деления на нуль. int numberl, number2; cin >> numberl >> number2; try { включает код, который может сгенерировать исключение float result = quotient (numberl, number2); cout Частное равно result endl; catch (DivideByZeroError error) { обработчик ошибки cout ОШИБКА: ; error.printMessage (); cout endl; return 1; завершение при ошибке return 0; нормальное завершение Введите два целых числа для расчета их частного: 7 3 Частное равно 2.333333 Введите два целых числа для расчета их частного: 23 О ОШИБКА: Деление на нуль Рис. 13.1. Простой пример обработки исключения деления на нуль (часть 2 из 2) Простой пример обработки исключения. Контроль ошибки деления на ноль, tinclude <iostream.h> Определение класса DivideByZeroError, используемого при обработке исключения, генерируемого делением на нуль, class DivideByZeroError { public: DivideByZeroError (): message ( Деление на нуль ) { } void printMessage () const {cout << message;) private: const char *message; Описание функции quotient. Используется, чтобы показать генерацию исключения при ошибке деления на нуль, float quotient (int numl, int num2) { if (num2 == 0) throw DivideByZeroError (); return (float) numl / num2; Рис. 13.1. Простой пример обработки исключения деления на нуль (часть 1 из 2) Управляющая программа main О { cout << Введите два целых числа для расчета их частного: Рассмотрим два приведенных результата работы программы. Первый иллюстрирует успешное выполнение. Во втором введен знаменатель, равный нулю; программа обнаруживает эту ошибку и выдает о ней сообщение. Теперь рассмотрите программу драйвер main. Программа предлагает ввести два целых числа. Обратите внимание на локализованное объявление переменных numberl и number2. Далее программа выполняет блок try, включающий код, который может возбудить исключение. Заметьте, что фактическое деление, которое может вызывать ошибку, не присутствует явно в блока try. Вызывается функция quotient, содержащая операцию деления. Как мы скоро увидим, функция quotient создает объект исключение деления на нуль. В общем случае ошибка может появляться при выполнении операторов, явно упомянутых в блоке try, или в вызовах функций или даже в глубоко вложенных вызовах функций, инициализированных оператором из блока try. После блока try записан блок catch, содержащий обработчик исключения для ошибки деления на нуль. Вообще, когда исключение генерируется внутри блока try, оно перехватывается блоком catch, в котором определен тип, соответствующий сгенерированному исключению. В программе на рис. 13.1. определено, что блок catch будет перехватывать объекты исключения типа DivideByZeroError; этот тип соответствует типу объекта исключения, генерируемого в функции quotient. Тело данного обработчика исключения просто выдает сообщение об ошибке и возвращает 1, что указывает на прерывание выполнения из-за ошибки. Но обработчики исключений могут быть, конечно, намного сложнее, чем этот. Если, в процессе выполнения код в блоке try не генерирует исключение, тогда все обработчики catch, следующие за блоком try, пропускаются и управление передается первой строке после блоков catch; в программе на рис. 13.1 выполняется оператор возврата return, который возвращает О, указывая на нормальное завершение работы. Теперь давайте исследуем описания класса DivideByZeroError и функции quotient. В функции quotient, когда условный оператор if определяет, что знаменатель равен нулю, выполняется оператор throw, который специфицирует имя конструктора объекта исключения. В результате создается объект класса DivideByZeroError. Этот объект будет перехвачен оператором catch (в котором специфицирован тип DivideByZeroError), расположенным после блока try. Конструктор класса DivideByZeroError просто копирует строку Деление на нуль в закрытый элемент данных message. Сгенерированный объект принимается как параметр в обработчике catch (в данном случае, как параметр error) и сообщение печатается путем обращения к открытой функции printMessage. Хороший стиль программирования 13.4 Избегайте имени Exception для любого класса исключения. Весьма вероятно, что это имя используется библиотеками, и возможно даже будет включено в развивающийся стандарт ANSI для C+-I-. Хороший стиль программирования 13.5 Привязка каждого типа ошибки времени выполнения к соответавенно названному объекту исключения улучшает ясность программы.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |