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

1 ... 175 176 177 [ 178 ] 179 180 181 ... 395


catch ( EHstate &eCbj ) {

модифицируем объект-искчение eCbj = severeErr;

повторно возбужденное искчение имеет значение severeErr throw;

catch-обработчика должна фигурировать ссылка:

Теперь eCbj ссылается на объект-исключение, созданный выражением throw, так что все изменения относятся непосредственно к исходному объекту. Поэтому при повторном возбуждении исключения далее передается модифицированный объект.

Таким образом, другая причина для объявления сс1лки в catch-обработчике заключается в том, что сделанные внутри обработчика модификации объекта-исключения в таком случае будут видны при повторном возбуждении исключения. (Третья причина будет рассмотрена в разделе 19.2, где м1 расскажем, как catch-обработчик вызывает виртуальные функции класса.)

11.3.4. Перехват всех исключений

Иногда функции нужно выполнить определенное действие до того, как она завершит обработку исключения, даже несмотря на то, что обработать его она не может. К примеру, функция захватила некоторый ресурс, скажем открыла файл или выделила

void manip() {

resource res;

res.lock(); захват ресурса

использование ресурса

действие, в результате которого возбуждено искчение res.release(); не выполняется, ес возбуждено искчение

память из хипа, и этот ресурс необходимо освободить перед выходом:

Если исключение возбуждено, то управление не попадет на инструкцию, где ресурс освобождается. Чтобы освободить ресурс, не пытаясь перехватить все возможные исключения (тем более, что мы не всегда знаем, какие именно исключения могут возникнуть), воспользуемся специальной конструкцией, позволяющей перехватывать любые исключения. Это не что иное, как предложение catch, в котором объявление исключения имеет вид (... ) и куда управление попадает при любом исключении. Например:

Так как eCbj не является ссылкой, то catch-обработчик получает копию объекта-исключения, так что любые модификации eCbj относятся к локальной копии и не отражаются на исходном объекте-исключении, передаваемом при повторном возбуждении. Таким образом, переданный далее объект по-прежнему имеет тип zeroCp.

Чтобы модифицировать исходный объект-исключение, в объявлении исключения внутри



управление попадает сюда при любом возбужденном исключении

catch (... ) {

здесь размещаем наш код

Конструкция catch(... ) используется в сочетании с повторным возбуждением исключения. Захваченный ресурс освобождается внутри составной инструкции в catch-обработчике перед тем, как передать исключение по цепочке вложенных вызовов в

void manip() {

resource res

res.lock();

использование ресурса

действие, в результате которого возбуждено исключение

catch (... ) {

res.release();

throw;

res.release(); не выполняется, ес возбуждено искчение

результате повторного возбуждения:

Чтобы гарантировать освобождение ресурса в случае, когда выход из mianip() происходит в результате исключения, мы освобождаем его внутри catch(... ) до того, как исключение будет передано дальше. Можно также управлять захватом и освобождением ресурса путем инкапсуляции в класс всей работы с ним. Тогда захват будет реализован в конструкторе, а освобождение - в автоматически вызываемом деструкторе. (С этим подходом м1 познакомимся в главе 19.)

Предложение catch(... ) используется самостоятельно или в сочетании с другими catch-обработчиками. В последнем случае следует позаботиться о правильной организации обработчиков, ассоциированных с try-блоком.

Catch-обработчики исследуются по очереди, в том порядке, в котором они записаны. Как только найден подходящий, просмотр прекращается. Следовательно, если предложение catch(...) употребляется вместе с другими catch-обработчиками, то оно должно быть

try {

stack.display();

for ( int ix = 1; ix < 51; ++x )

то же, что и выше

catch ( pushCnFull ) { } catch ( popCnEmpty ) { }

последним в списке, иначе компилятор выдаст сообщение об ошибке:

catch ( ... ) { } должно быть последним в списке catch-обработчиков

Упражнение 11.4



(a) class exceptionType { }; catch( exceptionType *pet ) { }

(b) catch(... ) { }

(c) enum mathErr { overflow, underflow, zeroDivide }; catch( mathErr &ref ) { }

(d) typedef int EXCPTYPE;

объект-исключение, который может быть перехвачен указанными обработчиками:

catch( EXCPTYPE ) { }

Упражнение 11.6

Объясните, что происходит во время раскрутки стека. Упражнение 11.7

Назовите две причины, по которым объявление исключения в предложении catch следует делать ссылкой.

Упражнение 11.8

На основе кода, написанного вами в упражнении 11.3, модифицируйте класс созданного исключения: неправильный индекс, использованный в операторе operator[](), должен сохраняться в объекте-исключении и затем выводиться catch-обработчиком. Измените программу так, чтобы operator[]() возбуждал при ее выполнении исключение.

11.4. Спецификации исключений

По объявлениям функций-членов pop() и push() класса iStack невозможно определить, что они возбуждают исключения. Можно, конечно, включить в объявление подходящий комментарий. Тогда описание интерфейса класса в заголовочном файле будет содержать

class iStack {

public:

...

void pop( int &value ); возбуждает popCnEmpty void push( int value ); возбуждает pushCnFull

void push( int value private:

...

документацию возбуждаемых исключений:

Но такое решение несовершенно. Неизвестно, будет ли обновлена документация при выпуске следующих версий iStack. Кроме того, комментарий не дает компилятору достоверной информации о том, что никаких других исключений функция не возбуждает. Спецификация исключений позволяет перечислить в объявлении функции все

Объясните, почему модель обработки исключений в C++ называется невозвратной. Упражнение 11.5

Даны следующие объявления исключений. Напишите выражения throw, создающие



1 ... 175 176 177 [ 178 ] 179 180 181 ... 395

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