Программирование >>  Обобщенные обратные вызовы 

1 ... 21 22 23 [ 24 ] 25 26 27 ... 84


int fC) throwС A, в );

Если будет сгенерировано исключение, которого нет в списке спецификации исключений, будет вызвана функция unexpectedC).

Пример 13-1

int f() throw(A,B) { А и В не связаны с С

throw с(); Будет вызвана функция unexpected

Вы можете зарегистрировать ваш собственный обработчик для этого случая при помощи стандартной функции set unexpected. Ваш обработчик не должен получать никаких параметров и не должен возвращать никаких значений.

void MyUnexpectedHandlerO { /* ... */ } std::set unexpected( &MyUnexpectedHandler );

Остается один вопрос - что может делать ваш обработчик? Единственное, чего он не может делать, - .это выйти из функиии при помощи оператора return. Поэтому у него есть два варианта действий:

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

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

Применение

Идея, лежащая в основе спецификаций исключений, очень проста: в программе С++ любая функция, если не указано иное, может генерировать исключения любого типа. Рассмотрим некоторую функцию Func.

2. Какие исключения мотуг быть сгенерированы каждой из перечисленных ниже функций. Пример 13-2(а)

int FuncО; Может генерировать любые исключения

По умолчанию в С++ функция Func может генерировать исключения любого типа, как сказано в комментарии к ней. Однако зачастую нам известно, что функция может генерировать только исключения определенных типов. В таком случае может оказаться разумным сообщить об этом компилятору и программисту. Например;

Пример 13-2(6)

int GuncQ throwO; не генерирует исключений

int Nunc о throw(А,в); может генерировать только А или в

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

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



Проблема первая - призраки типов

3. Является ли спецификация исключений частью типа функции? Обоснуйте свой ответ.

Джои Спайсер (John Spicer) из знаменитой Edison Design Group, автор большой части главы стандарта С++, посвященной шаблонам, назвал спецификации исключений С++ призрачными типами (shadow type). Одна из важнейших характеристик С++ -- строгая типизация, и это хорошо и правильно. Но почему же мы называем спецификации исключений призрачными типами, а не частью системы типов С++?

Причина проста, хотя и имеет двойное дно :

спецификации исключений не являются частью типов функций;

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

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

пример 13-3(а): спецификацию исключений нельзя

использовать в инструкции typedef.

void f() throw(A,в);

typedef void (*pf)() throw(A,B); ошибка

PF pf = f; невозможно из-за ошибки

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

Пример 13-3(6): все то же, но без typedef!

void fО throw(A,в);

void (*pf)() throw(A,B); ok

pf = f; ok

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

Пример 13-3(в): тоже вполне кошерно и с низким содержанием холестерина.. . :)

void fО throw(A,В);

void (*pf)() throw(A,B,c); ok

pf - f; ok, тип pf менее строгий

Спецификации исключений также участвуют в типах виртуальных функций, когда вы пытаетесь их перекрыть.

пример 13-3(г): спецификации исключений имеют значение

для виртуальных функций.

class С {

virtual void f() throw(A,в); некоторая спецификация

исключений

class D : С {

void fО; ошибка - спецификация

исключений менее строгая

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



Проблема вторая -- (не)понимание

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

4. Что собой представляют спецификации исключений и как они работают? Дайте точный ответ на поставленный вопрос.

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

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

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

Эти ожидания, увы, несколько обманчивы. Рассмотрим еще раз код примера 13-2(6).

пример 13-2(6): два потенциальных обмана

int GuncO throwO; не генерирует исключений <-?

int HuncO throw(A,B); может генерировать только А или в <-?

Корректны ли приведенные комментарии? Не совсем. Функция Gunc на самом деле может сгенерировать исключение, а функция nunc - сгенерировать исключение, отличное от А и в! Компилятор только гарантирует, что если это произойдет - он просто, не дрогнув, прикончит вашу программу.

Раз функции Gunc и Nunc могут сгенерировать все, что угодно, а не только обещанное, то компилятор не только не может полагаться на то, что этого не произойдет, но должен выполнять еще и роль полицейского, следя за тем, что именно генерируется в этих функциях и насколько оно соотносится с обещаниями, данными в спецификациях исключений. Если все же обещание будет нарушено, компилятор должен вызвать функцию unexpected, что в большинстве случаев приведет к завершению работы вашей профаммы. Почему? Потому что из этой функции есть только два пути, и ни один из них не является нормальным возвратом из функции. Выбирайте сами.

Можно сгенерировать исключение, которое разрешено спецификацией исключений. В этом случае распространение исключения продолжится как обычно. Но помните, что обработчик unexpected - глобальный, т.е. он один-единственный на всю программу. Вряд ли такой глобальный обработчик окажется достаточно разумным, чтобы выполнить нечто разумное в каждом частном случае, так что, скорее всего, путь один - вызов terminate...

Можно сгенерировать исключение, которое спецификацией исключений не разрешено. Если в спецификации исключений исходной функции имеется исключение bad exception, то далее будет распространяться именно оно. Ну, а если нет, то путь один - вызов terminate...

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

В начале ответа на четвертый вопрос мы видели, чего программисты ожидают от спецификаций исключений. Давайте внесем коррективы в эти ожидания.

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

Позволяют или запрещают компилятору выполнить определенную оптимизацию, основанную на знании о том,~что могут быть сгенерированы-тодысо перо



1 ... 21 22 23 [ 24 ] 25 26 27 ... 84

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