Любой класс имеет две стороны медали: интерфейс и реализацию. Чтобы хоть как-то упорядочить наши знания в этом вопросе, давайте порассуждаем, что и в каких случаях мы наследуем. С закрытым наследованием все вроде бы ясно: это — наследование реализации, так как ни клиенты, ни последующие наследники «не видят» интерфейса при закрытом наследовании, если только его специально не открыть.
Совсем другое дело — открытое наследование. Здесь все видят все, поэтому важно понимать, что и в каких случаях наследуется. Понятно, что интерфейс класса наследуется всегда. Но при открытом наследовании существуют важные концептуальные различия в наследовании обычных, виртуальных и чисто виртуальных функций.
Совершенно очевидно, что объявление чисто виртуальной функции предполагает наследование только интерфейса, оставляя реализацию классам-наследникам. Даже если чисто виртуальная функция имеет определение, это определение не наследуется и класс-наследник остается абстрактным.
Если функция не объявлена виртуальной, то изменение ее поведения в наследниках, очевидно, не предполагается. Поэтому можно сказать (хотя это и не поддерживается непосредственно в языке), что реализация невиртуальной функции является обязательной для классов-наследников — они не должны ее изменять.
Труднее разобраться, что же мы наследуем, если функция объявлена виртуальной. С одной стороны, мы вроде бы не собираемся наследовать реализацию — именно для этого функция объявлена виртуальной. С другой стороны, мы не объявили эту функцию чистой виртуальной — значит, предполагается, что реализация все-таки пригодится. Как правильно заметил Скотт Мейерс в [23], в этом случае мы наследуем реализацию по умолчанию: если мы не переопределим виртуальную функцию в наследнике, то будет работать базовая реализация по умолчанию.
Заметьте, что определение чистой виртуальной функции не является реализацией по умолчанию — мы должны явным образом вызывать такую функцию в методе-наследнике.
В [27] приводится интересная классификация форм наследования. Как и всякая классификация, эта — личное мнение автора книги [27]. Однако она может служить отправной точкой для понимания, с какой целью мы применяем этот мощнейший механизм — наследование. Автор считает, что порождение дочернего класса может быть выполнено по следующим причинам:
? Специализация. Класс-наследник является специализированной формой родительского класса — в наследнике просто переопределяются методы. Принцип подстановки выполняется. Очевидно, что такая форма наследования в С++ реализуется простым открытым наследованием. Примером является наследование часы будильник.
• Спецификация. Дочерний класс реализует поведение, описанное в родительском классе. Ясно, что в С++ эта форма реализуется простым открытым наследованием от абстрактного класса.
• Конструирование. Класс-наследник использует методы базового класса, но не является его подтипом (принцип подстановки не выполняется). В С++ такую форму можно реализовать простым закрытым наследованием.
• Расширение. В класс-потомок добавляют новые методы, расширяя поведение родительского класса; принцип подстановки в такой форме выполняется.
• Обобщение. Дочерний класс обобщает поведение базового класса. Обычно такое наследование требуется в тех случаях, когда мы не можем изменить поведение базового класса (например, базовый класс является библиотечным).
• Ограничение. Класс-наследник ограничивает поведение родительского класса. Очевидно, что в С++ такой вид наследования реализуется простым закрытым наследованием (пример — TDeque -> TStack).
• Варьирование. Базовый и производный классы являются вариациями на одну тему, однако связь «класс-подкласс» произвольна, например, «квадрат-прямоугольник» или «прямоугольник-квадрат» . Эта форма фактически не отличается от «конструирования», так как класс-наследник, очевидно, «использует методы базового класса, но не является его подтипом».
• Комбинирование. Дочерний класс наследует черты нескольких классов — это множественное наследование (см. главу 10).
Наследование — это огромный пласт С++, которого мы в этой главе только коснулись.
Опубликовал Kest
November 24 2013 04:18:09 ·
0 Комментариев ·
3559 Прочтений ·
• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •
Комментарии
Нет комментариев.
Добавить комментарий
Рейтинги
Рейтинг доступен только для пользователей.
Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.
Нет данных для оценки.
Гость
Вы не зарегистрированны? Нажмите здесь для регистрации.