Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Козин С. В. ООП. Лекции.doc
Скачиваний:
57
Добавлен:
06.07.2020
Размер:
489.47 Кб
Скачать

Объект исключения

Объект исключения автоматически создается компилятором. Он строится на основе того объекта, который «выбрасывает» инструкция throw. Например:

throw std :: length_error(“Недопустимо большой размер ” “объекта \n”);

После того как отработает инструкция throw, временный анонимный объект будет уничтожен. Но перед его уничтожением компилятор снимет копию с этого временного объекта. Эта копия будет сохранена компилятором в надежном месте. Указанная копия и называется объектом исключения. Объект исключения доступен любому обработчику catch, который способен обрабатывать данный тип исключений.

После создания объекта исключения управление должно покинуть тело той функции, в которой сгенерировано исключение. Однако до этого события компьютер должен выполнить так называемую раскрутку стека (stack unwinding).

Раскрутка стека

В процессе раскрутки стека происходит уничтожение локальных объектов. Для локальных объектов, имеющих пользовательский тип, автоматически вызываются деструкторы. Для удаления локальных объектов, имеющих встроенный тип, компилятор ничего не делает. Для объектов, созданных с помощью оператора new, компилятор не будет автоматически вызывать оператор delete с целью принудительного освобождения памяти.

Перейдем теперь к рассмотрению второй обязанности разработчика функции, которая состоит в том, что необходимо уведомить клиента о том какие исключения он должен обрабатывать. Одна из специальных возможностей предусмотрена стандартом языка C++. Эта возможность носит название спецификации исключения.

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

Это необязательная конструкция. Программист может ее записывать в объявлении и определении функции. Для определенности будем рассматривать объявление (прототип) функции, которое с учетом спецификаций исключения будет иметь следующую структуру.

<α>[β] ;

Здесь α – заголовок функции, β – необязательная спецификация исключения. Отметим, что имеются два формата спецификаций исключения.

  • throw(γ), где γ – список типов исключений.

  • throw().

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

Приведем пример.

class A { }; class B { }; class C { }; void f() throw(A, B); void h() throw();

В программном коде этого примера вначале имеются определения трех классов исключений с именами A, B и С. Затем приводятся прототипы двух функций, которые содержат спецификации исключений. Предполагается, что функция f() может выбросить исключения типа A и B. Функция h() не должна выбрасывать исключений.

Теперь казалось бы все хорошо. Клиент знает, что ему необходимо создать два обработчика catch. Один из них должен обрабатывать исключения типа A, а второй обработчик – для типа B.

Но что произойдет в том случае, когда функция выбросит исключение класса C. Это может, например, произойти так:

void f() throw(A, B) { //.. g(); } void g() { //.. throw C(); }

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