- •38 Наследование и проектирование
- •Глава 6 Наследование и объектно-ориентированное проектирование
- •Правило 32: Используйте открытое наследование для моделирования отношения «является»
- •Virtual void fly(); // птицы умеют летать
- •Virtual void healthValue() const; // возвращает жизненную силу персонажа
- •Реализация паттерна««Шаблонный метод» с помощью идиомы невиртуального интерфейса
- •Реализация паттерна «Стратегия» посредством указателей на функции
- •Реализация паттерна «Стратегия» посредством класса tr::function
- •Int operator()(const GameCharacter&) const // объектов, вычисляющих
- •«Классический» паттерн «Стратегия»
- •Void mf(); // скрывает b:mf; см. Правило 33
- •Virtual void onTick() const; // автоматически вызывается
- •Virtual void onTick() const; // просмотр данных об использовании
- •Что следует помнить
38 Наследование и проектирование
|
Начало формы
Конец формы |
[ Главная ] [ Гостевая ] |
|
|
[ Назад ] [ Содержание ] [ Вперед ]
Глава 6 Наследование и объектно-ориентированное проектирование
Глава 6 Наследование и объектно-ориентированное проектирование
Правило 32: Используйте открытое наследование для моделирования отношения «является»
Правило 33: Не скрывайте унаследованные имена
Правило 34: Различайте наследование интерфейса и наследование реализации
Правило 35: Рассмотрите альтернативы виртуальным функциям
Реализация паттерна««Шаблонный метод» с помощью идиомы невиртуального интерфейса
Реализация паттерна «Стратегия» посредством указателей на функции
Реализация паттерна «Стратегия» посредством класса tr::function
«Классический» паттерн «Стратегия»
Резюме
Правило 36: Никогда не переопределяйте наследуемые невиртуальные функции
Правило 37: Никогда не переопределяйте наследуемое значение аргумента функции по умолчанию
Правило 38: Моделируйте отношение «содержит» или «реализуется посредством» с помощью композиции
Правило 39: Продумывайте подход к использованию закрытого наследования
Правило 40: Продумывайте подход к использованию множественного наследования
Объектно-ориентированное программирование (ООП) существует почти 20 лет, поэтому, вероятно, вы имеете некоторое представление о наследовании, производных классах и виртуальных функциях. Даже если вы программировали только на C, ничего не слышать об ООП вы просто не могли.
И все же ООП в C++, скорее всего, несколько отличается от того, к чему вы привыкли. Наследование может быть одиночным и множественным, а отдельный путь наследования может быть открытым (public), защищенным (protected) или закрытым (private). Путь также может быть виртуальным или невиртуальным. Для функций-членов тоже есть варианты. Виртуальные? Невиртуальные? Чисто виртуальные? Добавьте сюда взаимодействие с другими средствами языка. Как соотносятся параметры по умолчанию с виртуальными функциями? Как влияет наследование на правила разрешения имен в C++? И что можно сказать по поводу методов проектирования? Если поведение класса должно быть модифицируемым, являются ли виртуальные функции лучшим способом достижения этого?
Обо всем этом пойдет речь в настоящей главе. Я объясню, что на самом деле стоит за теми или иными возможностями C++: какую мысль вывыражаете, когда используете некоторую конструкцию. Например, открытое наследование моделирует отношение «является», и если вы попытаетесь придать ему какую-то иную семантику, то столкнетесь с проблемой. Аналогично, виртуальная функция означает «должен быть унаследован интерфейс», в то время как невиртуальная функция означает «должны наследоваться и интерфейс, и реализация». Если не делать различий между этими смыслами, то неприятностей не миновать.
Когда вы поймете истинное назначение различных средств C++, то обнаружите, что ваш взгляд на ООП изменился. Вместо простого упражнения в нахождении отличий между языками это станет средством выражения того, что вы хотите сказать о своей программной системе. А поняв, что же вы в действительности имеете в виду, уже не составит большого труда перевести свои мысли этого на C++.