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

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


1. Исключения всегда возможны. Их может сгенерировать стандартная библиотека. Они могут порождаться языком п рограм миро ва н и я. Наш код должен быть к этому готов. К счастью, это небольшая беда, поскольку теперь мы знаем, что с ними делать. Нам надо просто принять некоторые правила поведения и строго им следовать.

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

2. Написание безопасного с точки зрения исключений кода - правило хорошего тона. Безопасность кода и его качество взаимосвязаны. Распространенные методы написания безопасного в плане исключений кода вполне применимы и в случае отсутствия исключений. Рассмотрим основные приемы, облегчающие написание безопасного кода.

Использование идиомы распределение ресурса есть инициализация для работы с ресурсами. Использование таких объектов-владельцев ресурсов, как классы Lock и shared ptr (см. [Boost, Suttert)2a]), - хорошая мысль безотносительно к безопасности исключений. Не удивительно, что к достоинствам таких классов относится и безопасность исключений. Сколько раз вам приходилось встречаться с функциями (понятно, что мы не говорим о ваших собственных функциях, разговор идет о чужом коде), в которых в ветви, приводящей к преждевременному возврату из функции, не выполнялось необходимое освобождение ресурсов? А ведь достаточно было использовать указанную идиому, и все эти действия были бы выполнены автоматически.

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

Следование принципу один класс (одна функция) -- одно действие . Функции, выполняющие несколько действий, например stack: :Рор или EvaluateSalaryAn-dReturnName из книги [SuttetOO], очень сложно сделать строго безопасными в смысле исключений. Многие проблемы, связанные с безопасностью исключений, можно реизить, просто придерживаясь указанного принципа. Это правило появилось задолго до того, как стало понятно, что оно применимо и к проблемам безопасности исключений; принцип одного действия ценен сам по себе.

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

Теперь, после всего сказанного, перед нами встает вопрос: когда и какую гарантию следует использовать? Вот правило, которому следует стандартная библиотека С+ + и которое вы с успехом можете применять в собственных программах.

> Рекомендация

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

Задача 12. Безопасность исключений: стоит ли овчинка выделки? 85



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

> Рекомендация

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

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

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

Дополнительную информацию о рассмотренных концепциях (например: что собой представляет бессбойная функция обмена swap или почему деструкторы не должны генерировать исключений) вы найдете в книгах [SutterOO] и [Sutter02].



Задача 13. Прагматичный взгляд

на спецификации исключений Сложность: 6

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

Вопрос для новичка

1. Что произойдет при нарушении спецификации исключений? Почему? Каковы основные причины существования этой возможности С++?

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

int FuncC);

int GuncQ throwO ;

int HuncQ throw(A,B);

Вопрос для профессионала

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

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

5. Когда стоит использовать спецификацию исключений в функции? Почему вы используете (или не используете) эту возможность?

Решение

Как вы знаете, сейчас идет работа над новым стандартом С++ (рабочее название С++Ох). Давайте оглянемся назад и постараемся осмыслить накопленный опыт работы с текущим стандартом [С++03]. Подавляющее большинство стандартных возмож-ностей С++ просто замечательны, и именно им посвящена львиная доля публикаций, что не удивительно - кому хочется твердить о недостатках! Слабые, мало используемые возможности языка чаше всего просто игнорируются и постепенно забываются (и это далеко не всегда плохо). Вот почему встречается очень мало статей о таких невразумительных возможностях языка, как vaiarray, bi tset и прочих - и в их число входят и спецификации исключений.

Давайте поближе познакомимся с имеющимся опытом использования стандартных спецификаций исключений С+ + .

Нарушение спецификации

1. Что произойдет при нарушении спецификации исключений? Почему? Каковы основные причины существования этой возможности С++?

Идея спецификаций исключений заключается в проверке времени выполнения того, что данная функция может генерировать только определенные типы исключений (либо не генерировать их вовсе). Например, приведенная ниже спецификация исключений гарантирует, что f может генерировать только исключения типа л или в *:

* Говоря точнее, если окружить эту функцию try/catch блоками для перехвата исключений А и В, то все возможные исключения будут перехвачены - в частности, такая функция может генерировать исключения, являющиеся производными классами от А и В. - Прим. ред.



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

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