Читаем Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ полностью

• Функции, предоставляющие базовую гарантию, обещают, что если исключение будет возбуждено, то все в программе остается в корректном состоянии. Никакие объекты или структуры данных не повреждены, и все объекты находятся в непротиворечивом состоянии (например, все инварианты классов не нарушены). Однако точное состояние программы может быть непредсказуемо. Например, мы можем написать функцию change-Background так, что при возникновении исключения объект PrettyMenu сохранит старую фоновую картинку либо у него будет какой-то фон по умолчанию, но пользователи не могут заранее знать, какой. (Чтобы выяснить это, им придется вызвать какую-то функцию-член, которая сообщит, какая сейчас используется картинка.)

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

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

• Функции, предоставляющие гарантию отсутствия исключений, обещают никогда не возбуждать исключений, потому что всегда делают то, что должны делать. Все операции над встроенными типами (например, целыми, указателями и т. п.) обеспечивают такую гарантию. Это основной строительный блок безопасного относительно исключений кода. Разумно предположить, что функции с пустой спецификацией исключений не возбуждают их, но это не всегда так. Например, рассмотрим следующую функцию:

int doSomething() throw(); // обратите внимание на пустую

// спецификацию исключений

Это объявление не говорит о том, что doSomething никогда не возбуждает исключений. Утверждается лишь, что если doSomething возбудит исключение, значит, произошла серьезная ошибка и должна быть вызвана функция unexpected[3]. Фактически doSomething может вообще не представлять никаких гарантий относительно исключений. Объявление функции (включающее ее спецификацию исключений) ничего не сообщает относительно того, является ли она корректной, переносима, эффективной, какие гарантии безопасности исключений она предоставляет и предоставляет ли их вообще. Все эти характеристики определяются реализацией функции, а не ее объявлением.

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

Вообще говоря, нужно стремиться предоставить максимально строгие гарантии. С точки зрения безопасности исключений функции, не возбуждающие исключений, чудесны, но очень трудно, не оставаясь в рамках языка C, обойтись без вызова функций, возбуждающих исключения. Любой класс, в котором используется динамическое распределение памяти (например, STL-контейнеры), может возбуждать исключение bad_alloc, когда не удается найти достаточного объема свободной памяти (см. правило 49). Предоставляйте гарантии отсутствия исключений, когда можете, но для большинства функций есть только выбор между базовой и строгой гарантией.

Для функции changeBackground предоставить почти строгую гарантию нетрудно. Во-первых, измените тип данных bgImage в классе PrettyMenu со встроенного указателя *Image на один из «интеллектуальных» управляющих ресурсами указателей, описанных в правиле 13. Откровенно говоря, это в любом случае неплохо, поскольку позволяет избежать утечек ресурсов. Тот факт, что это заодно помогает обеспечить строгую гарантию безопасности исключений, просто подтверждает приведенные в правиле 13 аргументы в пользу применения объектов (наподобие интеллектуальных указателей) для управления ресурсами. Ниже я воспользовался классом tr1::shared_ptr, потому что он ведет себя более естественно при копировании, чем auto_ptr.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных