Программирование >>  Инициализация объектов класса, структура 

1 ... 328 329 330 [ 331 ] 332 333 334 ... 395


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, то возбужденное исключение всегда имеет такой же тип, как и это



1 ... 328 329 330 [ 331 ] 332 333 334 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика