Ограничения, налагаемые на тип исключений, генерируемых функциями



 

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

 

 

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

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

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

 

 

В этой программе функция Xhandler() может генерировать исключения только типа int , char и double . При попытке сгенерировать исключение любого другого типа произойдет аварийное завершение программы (благодаря вызову функции unexpected() ). Чтобы убедиться в этом, удалите из throw ‑списка, например, тип int и перезапустите программу.

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

Следующее изменение помешает функции Xhandler() генерировать любые изменения.

 

 

На заметку. На момент написания этой книги среда Visual C++ не обеспечивала для функции запрет генерировать исключения, тип которых не задан в throw‑выражении. Это говорит о нестандартном поведении данной среды. Тем не менее вы все равно можете задавать "ограничивающее" throw‑выражение, но оно в этом случае будет играть лишь уведомительную роль.

 

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

 

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

Повторное генерирование исключения демонстрируется в следующей программе (в данном случае повторно генерируется тип char * ).

 

 

При выполнении эта программа генерирует такие результаты.

 

Обработка исключений, сгенерированных оператором new

 

В главе 9 вы узнали, что оператор new генерирует исключение, если не удается удовлетворить запрос на выделение памяти. Поскольку тема исключений рассматривается только в этой главе, описание обработки исключений этого типа было отложено "на потом" . Вот теперь настало время об этом поговорить.

Для начала необходимо отметить, что в этом разделе описывается поведение оператора new в соответствии со стандартом C++. Как было отмечено в главе 9, действия, выполняемые системой при неуспешном использовании оператора new , с момента изобретения языка C++ изменялись уже несколько раз. Сначала оператор new возвращал при неудаче значение null . Позже такое поведение было заменено генерированием исключения. Кроме того, несколько раз менялось имя этого исключения. Наконец, было решено, что оператор new будет генерировать исключения по умолчанию, но в качестве альтернативного варианта он может возвращать и нулевой указатель. Следовательно, оператор new в разное время был реализован различными способами. И хотя все современные компиляторы реализуют оператор new в соответствии со стандартом C++, компиляторы более "почтенного" возраста могут содержать отклонения от него. Если приведенные здесь примеры программ не работают с вашим компилятором, обратитесь к документации, прилагаемой к компилятору, и поинтересуйтесь, как именно он реализует функционирование оператора new .

Согласно стандарту C++ при невозможности удовлетворить запрос на выделение памяти, требуемой оператором new , генерируется исключение типа bad_alloc . Если ваша программа не перехватит его, она будет досрочно завершена. Хотя такое поведение годится для коротких примеров программ, в реальных приложениях необходимо перехватывать это исключение и разумно обрабатывать его. Чтобы получить доступ к исключению типа bad_alloc , нужно включить в программу заголовок <new> .

Рассмотрим пример использования оператора new , заключенного в try/catch ‑блок для отслеживания неудачных результатов запроса на выделение памяти.

 

 

При неудачном выполнении оператора new исключение в этой программе будет перехвачено catch ‑инструкцией. Этот же подход можно использовать для отслеживания любых ошибок, связанных с использованием оператора new : достаточно заключить каждую new ‑инструкцию в try ‑блок.

 


Дата добавления: 2018-09-22; просмотров: 434; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!