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

• Допустимо преобразование из производного типа в базовый.

• Массив преобразуется в указатель на тип массива; функция преобразуется в соответствующий указатель на тип функции.

Никакие другие преобразования при поиске соответствующего обработчика недопустимы. В частности, невозможны ни стандартные арифметические преобразования, ни преобразования, определенные для классов.

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

Повторная передача исключения

Вполне возможна ситуация, когда один блок кода catch (обработчик) не сможет полностью обработать исключение. После некоторых корректирующих действий обработчик может решать, что это исключение следует обработать в функции, которая расположена далее по цепи вызовов. Обработчик может передавать исключение другому, внешнему обработчику, который принадлежит функции, вызвавшей данную. Это называется повторной передачей исключения (rethrow). Повторную передачу осуществляет оператор throw, после которого нет ни имени типа, ни выражения.

throw;

Пустой оператор throw может присутствовать только в обработчике или в функции, вызов которой осуществляется из обработчика (прямо или косвенно). Если пустой оператор throw встретится вне обработчика, будет вызвана функция terminate().

Повторная передача не определяет нового исключения; по цепочке передается текущий объект исключения.

Обычно обработчик вполне может изменить содержимое своего параметра. Если после изменения своего параметра обработчик повторно передаст исключение, то эти изменения будут переданы далее, только если параметр обработчика объявлен как ссылка:

catch (my_error &eObj) { // спецификатор ссылочного типа

 eObj.status = errCodes::severeErr; // изменение объекта исключения

 throw; // переменная-член status объекта исключения имеет

        // значение severeErr

} catch (other_error eObj) { // спецификатор нессылочного типа

 eObj.status = errCodes::badErr; // изменение только локальной копии

 throw; // значение переменной-члена status объекта исключения

        // при повторной передаче не изменилось

}

Обработчик для всех исключений

Иногда необходимо обрабатывать все исключения, которые могут произойти, независимо от их типа. Обработка каждого возможного исключения может быть проблематична: иногда неизвестно, исключения каких типов могут быть переданы. Даже когда все возможные типы известны, предоставление отдельной директивы catch для каждого возможного исключения может оказаться весьма утомительным. Для обработки всех исключений в объявлении исключения используется многоточие. Такие обработчики, называемые обработчиками для всех исключений (catch-all), имеют форму catch(...). Такая директива соответствует исключениям любого типа.

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

void manip() {

try {

 // действия, приводящие к передаче исключения

} catch (...) {

 // действия по частичной обработке исключения

 throw;

}

Директива catch(...) применяется самостоятельно или в составе нескольких директив catch.

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

Упражнения раздела 18.1.2

Упражнение 18.4. Заглянув вперед в иерархию наследования на рис. 18.1, объясните, что неправильно в следующем блоке try. Исправьте его:

try {

 // использовать стандартную библиотеку С++

} catch(exception) {

 // ...

} catch(const runtime_error &re) {

 // ...

} catch(overflow_error eobj) { /* ... */ }

Упражнение 18.5. Измените следующую функцию main() так, чтобы обрабатывались исключения любых типов, представленных на рис. 18.1:

int main() {

 // использовать стандартную библиотеку С++

}

Перейти на страницу:

Похожие книги