Чтение онлайн

на главную - закладки

Жанры

Стандарты программирования на С++. 101 правило и рекомендация

Александреску Андрей

Шрифт:

Композиция имеет важные преимущества над наследованием.

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

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

• Большая обособленность в процессе компиляции, уменьшение времени компиляции. Хранение объекта посредством указателя (предпочтительно — интеллектуального указателя), а не в виде непосредственного члена или базового класса позволяет также снизить зависимости заголовочных файлов, поскольку объявление указателя на объект не требует полного определения класса этого объекта. Наследование, напротив, всегда требует видимости полного определения базового класса. Распространенная методика состоит в том, чтобы собрать все закрытые члены воедино посредством одного непрозрачного указателя (идиома Pimpl, см. рекомендацию 43).

• Меньше странностей. Наследование от некоторого типа может вызвать проведение поиска имен среди функций и шаблонов функций, определенных в том же пространстве имен, что и упомянутый тип. Этот тонкий момент с трудом поддается отладке (см. также рекомендацию 58).

• Большая применимость. Не все классы проектируются с учетом того, что они будут выступать в роли базовых (см. рекомендацию 35). Однако большинство классов вполне могут справиться с ролью члена.

• Большая надежность и безопасность. Более сильное связывание путем наследования затрудняет написание безопасного в смысле ошибок кода (см. [Sutter02] §23).

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

Конечно, это все не аргументы против наследования как такового. Наследование предоставляет программисту большие возможности, включая заменимость и/или возможность перекрытия виртуальных функций (см. рекомендации с 36 по 39 и подраздел исключений данной рекомендации). Но не платите за то, что вам не нужно; если вы можете обойтись без наследования, вам незачем мириться с его недостатками.

Исключения

Используйте открытое наследование для моделирования заменимости (см. рекомендацию 37).

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

• Если вам требуется перекрытие виртуальной функции.

• Если вам нужен доступ к защищенному члену.

• Если вам надо создавать объект до используемого, а уничтожать — после, сделайте его базовым классом.

• Если вам приходится заботиться о виртуальных базовых классах.

• Если вы знаете, что получите выгоду от оптимизации пустого базового класса и что в вашем случае она будет выполнена используемым

вами компилятором (см. рекомендацию 8).

• Если вам требуется управляемый полиморфизм, т.е. отношение заменимости, которое должно быть видимо только определенному коду (посредством дружбы).

Ссылки

[Cargill92] pp. 49-65, 101-105 • [Cline99] §5.9-10, 8.11-12, 37.04 • [Dewhurst03] §95 • [Lakos96] §1.7, §6.3.1 • [McConnell93] §5 • [Meyers97] §40 • [Stroustrup00] §24.2-3 • [Sutter00] §22-24, §26-30 • [Sutter02] §23

35. Избегайте наследования от классов, которые не спроектированы для этой цели

Резюме

Классы, предназначенные для автономного использования, подчиняются правилам проектирования, отличным от правил для базовых классов (см. рекомендацию 32). Использование автономных классов в качестве базовых является серьезной ошибкой проектирования и его следует избегать. Для добавления специфического поведения предпочтительно вместо функций-членов добавлять обычные функции (см. рекомендацию 44). Для того чтобы добавить состояние, вместо наследования следует использовать композицию (см. рекомендацию 34). Избегайте наследования от конкретных базовых классов.

Обсуждение

Использование наследования там, где оно не требуется, подрывает доверие к мощи объектно-ориентированного программирования. В C++ при определении базового класса следует выполнить некоторые специфические действия (см. также рекомендации 32, 50 и 54), которые весьма сильно отличаются (а зачастую просто противоположны) от действий при разработке автономного класса. Наследование от автономного класса открывает ваш код для массы проблем, причем ваш компилятор в состоянии заметить только их малую часть.

Начинающие программисты зачастую выполняют наследование от классов-значений, таких как класс

string
(стандартный или иной) просто чтобы "добавить больше функциональности". Однако определение свободной функции (не являющейся членом) существенно превосходит создание класса
super_string
по следующим причинам.

• Свободные функции хорошо вписываются в существующий код, который работает с объектами

string
. Если же вместо этого вы предоставляете класс
super_string
, вам придется вносить изменения в ваш код, заменяя типы и сигнатуры функций.

• Функции интерфейса, которые получают параметры типа

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

• Функции-члены

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

Поделиться:
Популярные книги

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Светлая тьма. Советник

Шмаков Алексей Семенович
6. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Светлая тьма. Советник

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Его нежеланная истинная

Кушкина Милена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Его нежеланная истинная

Последний Паладин. Том 2

Саваровский Роман
2. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 2

Измена. Наследник для дракона

Солт Елена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Измена. Наследник для дракона

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Мастер темных Арканов

Карелин Сергей Витальевич
1. Мастер темных арканов
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Мастер темных Арканов

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Кодекс Охотника. Книга XXI

Винокуров Юрий
21. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XXI

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

Законы Рода. Том 3

Flow Ascold
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник