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



• Если вы знаете, что получите выгоду от оптимизации пустого базового класса и что в вашем случае она будет выполнена используемым вами компилятором (см. рекомендацию 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, при использовании наследования должны сделать одно из трех: а) отказаться от дополнительной функциональности