|
Программирование >> Структурное программирование
13.10. Создание условного выражения Можно генерировать условное выражение. Но будьте внимательны, потому что правила приведения типов могут привести к тому, что значение, возвращаемое условным выражением, будет иметь тип, отличный от ожидаемого. Например, при генерации или int, или double из одного и того же условного выражения это условное выражение преобразует int в double. Следовательно результат будет всегда перехватываться обработчиком catch с параметром типа double, а не в зависимости от результата иногда перехватываться обработчиком double (если результат действительно double), а иногда - обработчиком int. 13.11. Спецификация исключений в описании функции может быть указана спецификация исключений - список исключений, которые могут генерироваться этой функцией: int g (float h) throw (a, b, c) { тело функции } Можно ограничить типы исключений, которые могут генерироваться данной функцией. Типы исключений специфицируются в объявлении функции как спецификация исключений. Эта спецификация перечисляет исключения, которые могут быть сгенерированы в функции. Функция может генерировать обозначенные исключения или типы, производные от них. Хотя при этом предполагается гарантия, что другие типы исключений генерироваться не будут, генерация их все-таки возможна. Если генерируется исключение, не перечисленное в спецификации, вызывается функция обработки непредусмотренных исключений unexpected. Типичная ошибка программирования 13.10 Размещение пустого оператора throw вне обработчика catch; выполнение такого оператора throw вызовет обращение к terminate. Даже если обработчик может обработать исключение и независимо от того, делает ли он какую-либо обработку этого исключения, он может повторно возбудить исключение для последующей обработки его вне этого обработчика. Повторно сгенерированное исключение обнаруживается следующим внешним блоком try и перехватывается обработчиком из списка, следующего за этим внешним блоком try. Замечание по технике программирования 13.11 Используйте catch (...), чтобы выполнить восстановления, которые не зависят от типа исключения, например, освобождение общих ресурсов. Исключение может быть повторно сгенерировано для применения к нему более специфических обработок во внешних блоках catch. Появление throw () (то есть пустой спецификации исключений) после списка параметров функции объявляет, что функция не будет вырабатывать никаких исключений. На самом же деле такая функция могла бы возбудить исключение; это привело бы к вызову функции unexpected. Типичная ошибка программирования 13.11 Генерация исключения, не перечисленного в спецификации исключений функции, вызывает обращение к unexpected. Функция без спецификации исключений может генерировать любое исключение: void g О; эта функция может генерировать любое исключение Функции, содержащие пустую спецификацию исключений, не генерируют исключений: void g О throw (); эта функция не генерирует никаких исключений Функция unexpected может быть переопределена с помощью функции set unexpected. Интересным аспектом обработки исключений является то, что компилятор не будет рассматривать как ошибку компиляции случай, когда функция содержит выражение throw для исключения, не перечисленного в спецификации исключений данной функции. Функция должна попытаться сгенерировать такое исключение во время выполнения прежде, чем эта ошибка будет перехвачена. Если функция генерирует исключение некоторого класса, то эта функция может также генерировать исключения всех классов, которые являются производными от этого класса. Никакая спецификация исключения не означает, что функция может генерировать любое исключение. 13.12. Обработка непредусмотренных исключений Функция unexpected вызывает функцию, определенную с помощью функции set unexpected. Если нет функции, определенной таким способом, то по умолчанию вызывается функция завершения программы terminate. Функция terminate может быть вызвана различными путями: явно; если сгенерированное исключение не может быть перехвачено; если во время обработки исключения разрушен стек; как заданное по умолчанию действие при вызове unexpected; во время разматывания стека, вызванного исключением, и попытки со стороны деструктора сгенерировать исключение, что вызывает обращение к terminate. Функция set terminate может задавать функцию, которая будет вызываться при вызове terminate. Иначе, terminate вызывает abort. Прототипы функций set terminate и set unexpected находятся в заголовочных файлах <terminate.h> и <unexpected.h> соответственно. Функции set terminate и set unexpected возвращают указатели на предыдущие версии функции terminate и unexpected соответственно. Это дает возможность программисту сохранить указатели на эти функции, так что впоследствии они могут быть восстановлены. Функции set terminate и set unexpected получают в качестве аргументов указатели на функции. Каждый аргумент должен указывать на функцию, возвращающую тип void и без аргументов. Если последним действием определенной пользователем функции завершения не является завершение работы программы, то автоматически будет вызываться функция abort для прекращения работы программы после выполнения других операторов определенной пользователем функции завершения. 13.13. Конструкторы, деструкторы и обработка исключений Сначала давайте разберемся с проблемой, которую мы упомянули, но которая еще не было удовлетворительно решена. Что случится, когда ошибка обнаружена в конструкторе? Например, как должен реагировать конструктор строки String, когда операция new возвращает нуль, указывающий, что в памяти нет достаточного места для хранения внутреннего представления строки String? Проблема состоит в том, что поскольку конструктор не может возвратить значение, то как мы информируем внешний мир, что объект не был нормально создан? Один вариант - просто возвратить неправильно созданный объект и надеяться, что фрагменты программы, использующие данный объект, проверят его и определят, что объект неверный. Другой вариант состоит в том, чтобы установить некоторую переменную вне конструктора. Генерируемое исключение передает внешнему миру информацию о безуспешной работе конструктора и дает возможность обработать этот отказ. Чтобы перехватить исключение, обработчик должен иметь доступ к конструктору копии сгенерированного объекта (копия по умолчанию тоже подойдет). Исключения, генерируемые в конструкторах, обусловливают вызов деструкторов всех объектов, являющихся частями того объекта, который создавался перед генерацией исключения. Деструкторы вызываются для каждого автоматического объекта, созданного в блоке try до генерации исключения (это называется разматыванием стека). Исключение обрабатывается в момент, когда начинает выполняться обработчик; разматывание стека гарантированно завершается к этому времени. Если деструктор, вызываемый в результате разматывания стека, генерирует исключение, то вызывается функция завершения terminate. Если объект имеет объекты-элементы и если исключение сгенерировано прежде, чем вмещающий объект полностью создан, тогда деструкторы будут выполняться для объектов-элементов, которые были созданы до генерации исключения. Если к моменту генерации исключения был частично создан массив объектов, то будут выполняться деструкторы только созданных элементов массива.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |