Типы наследования. Видимость членов классов.
Наследование
Наследование -- такое отношение между классами когда один из них наследует (повторяет) структуру и поведение другого. Содержание (переменные-члены) и поведение (функции-члены) наследуются и становятся членами другого класса (наследника).
class Lens { private: Position m_p; Media m_media; double m_R1, m_R2; double m_d, m_D; };
| Например, оптические детали линза и зеркало могут быть реализованы, как обычные классы. Но, как видим, они имеют несколько атрибутов, которые характеризуют их, как оптическую деталь вообще. Имеет смысл воспользоваться принципом наследования и реализовать, базовый класс Detail.
| class Mirror { Position m_p; double m_R; double m_D; };
|
Создание базовых классов и классов-наследников в языке С++ осуществляется следующим образом.
| class Detail { protected: Position m_p; double m_D; };
| Базовым может стать любой класс и для этого никаких особых синтаксических конструкций не требуется.
|
class Lens: public Detail { private: Media m_media; double m_R1, m_R2; double m_d; };
| При создании классов-наследников необходимо указать базовый класс, от которого осуществляется наследование, а также тип наследования.
| class Mirror:public Detail { private: double m_R; };
|
Таким образом, и Lens и Mirror являются деталями, а соответствующие данные являются также членами этих классов.
Доступ к членам класса
|
| public (открытые)
| protected (защищенные)
| private (закрытые)
| функции-члены и друзья класса
| +
| +
| +
| функции-члены и друзья производных классов
| +
| +
| -
| пользователи
| +
| -
| -
|
|
class X: public Y;
| В этом случае наследник является подтипом и должен выполнять все обязательства родителя. Допустимо преобразование X* в Y*
|
class X: private Y;
| Наследуя структуру и поведение родителя наследник не будет его подтипом. public и protected члены родителя станут private членами наследника. Преобразование X* в Y* допустимо для друзей и членов X. Последующее наследование не имеет смысла.
|
class X: protected Y;
| Наследуя структуру и поведение наследник не будет подтипом. public и protected члены родителя станут protected членами наследника. Преобразование X* в Y* допустимо для членов и друзей и наследников X
|
Доступ к переменным-членам базового класса при различных типах наследования:
| public (открытые)
| protected (защищенные)
| private (закрытые)
|
public-наследование
| public
| protected
| недоступны
|
protected-наследование
| protected
| protected
| недоступны
|
private-наследование
| private
| private
| недоступны
|
При создании экземляра класса Lens будет вызван сначала конструктор базового класса (Detail()) и только после этого конструктор класса Lens(). При разрушении экземпляра класса Lens деструкторы будут вызваны в обратном порядке: сначала - деструктор ~Lens(), а затем - ~Detail().
class Detail { public: Detail(Posotion p, double D); }; Detail::Detail(Posotion p, double D) {... }
| class Lens:public Detail { public: Lens(Posotion p, Media* media, double D, double r1, double r2, double d); }; Lens::Lens(Posotion p, Media* media, double D, double r1, double r2, double d):Detail(p,media,D) {... }
|
В конструкторе наследника следует вызывать конструктор базового класса. Если этого не сделать, то компилятор попытается подставить конструктор по умолчанию. Если и его нет, то компилятор выбаст сообщение об ошибке.
class Base1 { public: Base1(); ~Base1(); };
| В языке С++ можно реализовать и множественное наследование:
| class Base2 { public: Base2(); ~Base2(); };
|
При создании экземляра класса Child конструкторы будут вызваны в следующей последовательности: Base1(), Base2() и только после этого конструктор класса Child().
| class Child: public Base1, public Base2 { public: Child(); ~Child(); };
| При разрушении экземпляра класса Child деструкторы будут вызваны в обратном порядке: сначала - деструктор ~Child(), затем - ~Base2(), а затем ~Base1().
|