Анимация
JavaScript
|
Главная Библионтека То есть, если ваша функция в состоянии обеспечить бессбойиую гарантию без ущерба для вызывающей функции, которой такая степень гарантии не нужна, то эту гарантию следует обеспечить. Заметим также, что некоторое количество ключевых функций просто обязано обеспечивать гарантию бессбойности. > Рекомендация Никогда не позволяйте генерировать исключения деструкторам, функциям, освобождающим ресурсы, и функциям обмена, поскольку в противном случае зачастую оказывается невозможно надежно и безопасно выполнить освобождение распределенных ресурсов. В противном случае, если ваша функция в состоянии обеспечить строгую гарантию без ущерба для пользователей, вы должны это сделать. Заметим, что vector: :insert представляет собой пример функции, которая в общем случае не поддерживает строгую гарантию, поскольку для этого требуется создание полной копии содержимого вектора при каждой вставке элемента, и далеко не всем программам настолько необходима строгая гарантия безопасности, чтобы платить за нее такую большую цену. (Программы, которым крайне необходима строгая гарантия безопасности исключений, могут легко добиться этого при помощи функции-оболочки вокруг vector: :insert, которая будет копировать вектор, выполнять вставку в копию, и в случае удачного выполнения этих операций обменивать содержимое копии и исходного вектора.) В противном случае ваша функция должна обеспечивать базовую гарантию. Дополнительную информацию о рассмотренных концепциях (например: что собой представляет бессбойная функция обмена swap или почему деструкторы не должны генерировать исключений) вы найдете в книгах [SutterOO] и [Sutter02]. Задача 13. Прагматичный взгляд на спецификации исключений Сложность: 6 Сейчас, когда сообществом программистов на С++ накоплен определенный опыт работы со спецификациями исключений, пришло время систематизировать его. Наша задача посвящена вопросу применения спецификаций исключений с учетом особенностей различных реальных компиляторов. Вопрос для новичка 1. Что произойдет при нарушении спецификации исключений? Почему? Каковы основные причины сушсствования этой возможности С++? 2. Какие исключения могут быть сгенерированы каждой из перечисленных ниже функций. int FuncC); int GuncQ throwO ; int HuncC) throw(A,B); Вопрос для профессионала 3. Является ли спецификация исключений частью типа функции? Обоснуйте свой ответ. 4. Что собой представляют спецификации исключений и как они работают? Дайте точный ответ на поставленный вопрос. 5. Когда стоит использовать спецификацию исключений в функции? Почему вы используете (или НС используете) эту возможность? Решение Как вы знаете, сейчас идет работа над новым стандартом С++ (рабочее название С++Ох). Давайте оглянемся назад и постараемся осмыслить накопленный опыт работы с текущим стандартом [С++03]. Подавляющее большинство стандартных возмож-ностей С++ просто замечательны, и именно им посвящена львиная доля публикаций, что НС удивительно - кому хочется твердить о недостатках! Слабые, мало используемые возможности языка чаще всего просто игнорируются и постепенно забываются (и это далеко не всегда плохо). Вот почему встречается очень мало статей о таких невразумительных возможностях языка, как valarray, bi tset и прочих - и в их число входят и спецификации исключений. Давайте поближе познакомимся с имеющимся опытом использования стандартных спецификаций исключений С+ + . Нарушение спецификации 1. Что произойдет при нарушении спецификации исключений? Почему? Каковы основные причины существования этой возможности С++? Идея спецификаций исключений заключается в проверке времени выполнения того, что данная функция может генерировать только определенные типы исключений (либо не генерировать их вовсе). Например, приведенная ниже спецификация исключений гарантирует, что f может генерировать только исключения типа л или в"*: * Говоря точнее, если окружить эту функцию try/catch блоками для перехвата исключений АиВ, то все возможные исключения будут перехвачены - в частности, такая функция может генерировать исключения, являющиеся производными классами or АиВ. - Прим. ред. int fC) throwC A, в ); Если будет сгенерировано исключение, которого нет в списке спецификации исключений, будет вызвана функция unexpectedC). Пример 13-1 int fС) throw(A,B) { А и в не связаны с С throw сС); Будет вызвана функция unexpected Вы можете з а р е г и с тр и р о вать ваш собственный обработчик для этого случая при помоши стандартной функции set unexpected. Ваш обработчик не должен получать никаких параметров и не должен возвращать никаких значений. void MyUnexpectedhandlerC) { /* ... */ } std::set unexpectedC &MyUnexpectedHandlег ); Остается один вопрос - что может делать ваш обработчик? Единственное, чего он не может делать, - .это выйти из функции при помощи оператора return. Поэтому у него есть два варианта действий: • преобразовать исключение в другое, допустимое спецификацией исключений, путем генерации исключения типа, имеющегося в списке спецификации исключений, вызвавшего вызов обработчика. Свертка стека при этом продолжится с того места, где она остановилась; • вызвать функцию terminate, которая завершает работу программы. (Функция terminate также может быть заменена другой, но в любом случае она должна завершить выполнение программы.) Применение Идея, лежащая в основе спецификаций исключений, очень проста: в программе С++ любая функция, если не указано иное, может генерировать исключения любого типа. Рассмотрим некоторую функцию Func. 2. Какие исключения мотуг быть сгенерированы каждой из перечисленных ниже функций. Пример 13-2Са) int FuncО; Может генерировать любые исключения По умолчанию в С++ функция Func может генерировать исключения любого типа, как сказано в комментарии к ней. Однако зачастую нам известно, что функция может генерировать только исключения определенных типов. В таком случае может оказаться разумным сообщить об этом компилятору и программисту. Например: Пример 13-2(6) int GuncO throwO; не генерирует исключений int Nunc о throw(А,в); может генерировать только А или в В приведенном примере спецификации исключений использованы для того, чтобы дать дополнительную информацию о функциях, а именно - о типах исключений, которые они могут генерировать. Комментарии, приведенные рядом с функциями, переводят спецификации исключений на обычный русский язык. Первая мысль по этому поводу - чем больше информации, тем лучше, так что указание спецификации исключений функции - это всегда не плохо. Но это не обязательно так, поскольку зачастую в излишней детализации и кроется зло: хотя намерения у спецификаций исключений и благие, вымощенный ими путь может завести нас не совсем туда, куда хотелось бы. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [ 24 ] 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |