Александреску Андрей
Шрифт:
Рассмотрим также еще один редкий случай.
• В одновременно является как базовым классом, так и конкретным классом, для которого могут создаваться объекты (так что деструктор этого класса должен быть открытым, чтобы было можно создавать и уничтожать объекты данного типа).
• У В нет виртуальных функций, и он не предназначается для полиморфного использования (так что хотя деструктор и открыт, он не обязан быть виртуальным).
Тогда несмотря на то, что деструктор оказывается открытым, имеется огромный соблазн не делать его виртуальным, поскольку такая первая виртуальная функция может привести к излишним расходам времени выполнения из-за добавления функциональности, которая нам совсем не нужна.
В этом редком случае вы можете сделать конструктор открытым и невиртуальным, но четко документировать, что производные объекты не могут использоваться полиморфно в качестве объектов базового класса. Именно это было сделано в случае класса
В общем случае, однако, следует избегать конкретных базовых классов (см. рекомендацию 35). Например,
[Cargill92] pp. 77-79, 207 • [Cline99] §21.06, 21.12-13 • [Henricson97] pp. 110-114 • [Koenig97] Chapters 4,11 • [Meyers97] §14 • [Stroustrup00] §12.4.2 • [Sutter02] §27 • [Sutter04] § 18
51. Деструкторы, функции освобождения ресурсов и обмена не ошибаются
Все запуски этих функций должны быть успешными. Никогда не позволяйте ошибке выйти за пределы деструктора, функции освобождения ресурса (например, оператора delete) или функции обмена. В частности, типы, деструкторы которых могут генерировать исключения, категорически запрещено использовать со стандартной библиотекой С++.
Перечисленные функции не должны генерировать исключений, так как они являются ключевыми для двух главных операций транзакционного программирования — отката при возникновении проблем в процессе работы и принятия результата работы, если проблем не возникло. Если нет способа безопасного возврата в предыдущее состояние при помощи операций, не генерирующих исключения, то невозможно реализовать бессбойный откат; отсутствие возможности безопасного сохранения изменения состояния при помощи операции, не генерирующей исключения, делает невозможной реализацию бессбойного принятия результата работы.
Рассмотрим следующие советы и требования, найденные в Стандарте С++.
Если деструктор, вызванный в процессе свертки стека, выходит с исключением, вызывается функция
В стандартной библиотеке C++ не определен ни один деструктор [включая деструкторы любого типа, используемого для инстанцирования шаблона стандартной библиотеки], генерирующий исключение.
— [C++03] §17.4.4.8(3)Деструкторы являются специальными функциями, и компилятор автоматически вызывает их в различных контекстах. Если вы пишете класс — назовем его, к примеру,
• Объекты
2
Nefarious — нечестивый, гнусный (англ.). — Прим. перев.
• Трудно безопасно использовать классы с членами или базовыми классами
• Вы не можете надежно создавать глобальные либо статические объекты
• Вы не можете надежно создавать массивы объектов