|
Программирование >> Инициализация объектов класса, структура
class popCnEmpty { ... }; функциями-членами нашего класса iStack: class pushCnFull { ... }; В реальных программах на C++ типы классов, представляющих исключения, чаще всего организуются в группы, или иерархии. Как могла бы выглядеть вся иерархия для этих классов? Мы можем определить базовый класс Excp, которому наследуют оба наши класса исключений. Он инкапсулирует данные и функции-члены, общие для обоих class Excp { ... }; class popCnEmpty : public Excp { ... }; производных: class pushCnFull : public Excp { ... }; Одной из операцией, которые предоставляет базовый класс, является вывод сообщения об class Excp public: напеч itic void print( string msg ) { cerr << msg << endl; напечатать сообщение об ошибке static ошибке. Эта возможность используется обоими классами, стоящими ниже в иерархии: 19.2. Исключения и наследование Обработка исключений - это стандартное языковое средство для реакции на аномальное поведение программы во время выполнения. C++ поддерживает единообразный синтаксис и стиль обработки исключений, а также способы тонкой настройки этого механизма в специальных ситуациях. Основы его поддержки в языке C++ описаны в главе 11, где показано, как программа может возбудить исключение, передать управление его обработчику (если таковой существует) и как обработчики исключений ассоциируются с try-блоками. Возможности механизма обработки исключений становятся больше, если в качестве исключений использовать иерархии классов. В этом разделе мы расскажем, как писать программы, которые умеют возбуждать и обрабатывать исключения, принадлежащие таким иерархиям. 19.2.1. Исключения, определенные как иерархии классов В главе 11 мы использовали два типа класса для описания исключений, возбуждаемых class Excp { ... }; class stackExcp : public Excp { ... }; class popCnEmpty : public stackExcp { ... }; программой: class mathExcp : public Excp ( ... }; class zeroCp : public mathExcp { ... }; class pushCnFull : public stackExcp { ... }; class divideByZero : public mathExcp { ... }; Последующие уточнения позволяют более детально идентифицировать аномальные ситуации в работе программы. Дополнительные классы исключений организуются как слои. По мере углубления иерархии каждый новый слой описывает все более специфичные исключения. Например, первый, самый общий слой в приведенной выше иерархии представлен классом Excp. Второй специализирует Excp, выделяя из него два подкласса: stackExcp (для исключений при работе с нашим iStack) и miathExcp (для исключений, возбуждаемых функциями из математической библиотеки). Третий, самый специализированный слой данной иерархии уточняет классы исключений: popCnEmpty и pushCnFull определяют два вида исключений работы со стеком, а ZeroCp и divideByZero - два вида исключений математических операций. В последующих разделах мы рассмотрим, как возбуждаются и обрабатываются исключения, представленные классами в нашей иерархии. 19.2.2. Возбуждение исключения типа класса Теперь, познакомившись с классами, посмотрим, что происходит, когда функция-член void iStack::push( int value ) if ( full() ) value throw pushCnFull( value ); value сохраняется в объекте-искчении push() нашего iStack возбуждает исключение: Выполнение инструкции throw инициирует несколько последовательных действий: 1. Инструкция throw создает временный объект типа класса pushCnFull, вызывая его конструктор. 2. С помощью копирующего конструктора генерируется объект-исключение типа pushCnFull - копия временного объекта, полученного на шаге 1. Затем он передается обработчику исключения. 3. Временный объект, созданный на шаге 1, уничтожается до начала поиска обработчика. Иерархию классов исключений разрешается развивать и дальше. От Excp можно произвести другие классы для более точного описания исключений, обнаруживаемых void iStack::push( int value ) { if ( full() ) { pushCnFull except( value ); stackExcp *pse = Sexcept; throw *pse; объект-искчение имеет тип stackExcp значение: Выражение *pse имеет тип stackExcp. Тип созданного объекта-исключения -stackExcp, хотя pse ссылается на объект с фактическим типом pushCnFull. Фактический тип объекта, на который ссылается throw, при создании объекта-исключения не учит1вается. Поэтому исключение не будет перехвачено catch-обработчиком pushCnFull. Действия, выполняемые инструкцией throw, налагают определенные ограничения на то, какие классы можно использовать для создания объектов-исключений. Оператор throw в функции-члене push() класса iStack вызовет ошибку компиляции, если: в классе pushCnFull нет конструктора, принимающего аргумент типа int, или этот конструктор недоступен; в классе pushCnFull есть копирующий конструктор или деструктор, но хотя бы один из них недоступен; pushCnFull - это абстрактный базовый класс. Напомним, что программа не может создавать объекты абстрактных классов (см. раздел 17.1). 19.2.3. Обработка исключения типа класса Если исключения организуются в иерархии, то исключение типа некоторого класса может быть перехвачено обработчиком, соответствующим любому его открытому базовому классу. Например, исключение типа pushCnFull перехватывается обработчиками исключений типа stackExcp или Excp. Зачем нужно генерировать объект-исключение (шаг 2)? Инструкция throw pushCnFull( value ); создает временный объект, который уничтожается в конце работы throw. Но исключение должно существовать до тех пор, пока не будет найден его обработчик, а он может находиться намного выше в цепочке вызовов. Поэтому необходимо скопировать временный объект в некоторую область памяти (объект-исключение), которая гарантированно существует, пока исключение не будет обработано. Иногда компилятор создает объект-исключение сразу, минуя шаг 1. Однако стандарт этого не требует, да и не всегда такое возможно. Поскольку объект-исключение создается путем копирования значения, переданного инструкции throw, то возбужденное исключение всегда имеет такой же тип, как и это
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |