Множественное наследование
Типы наследования. Видимость членов классов.
Наследование
Наследование -- такое отношение между классами когда один из них наследует (повторяет) структуру и поведение другого. Содержание (переменные-члены) и поведение (функции-члены) наследуются и становятся членами другого класса (наследника).
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 являются деталями, а соответствующие данные являются также членами этих классов.
Доступ к членам класса
|
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(). |