Множественное наследование

Типы наследования. Видимость членов классов.

Наследование

Наследование -- такое отношение между классами когда один из них наследует (повторяет) структуру и поведение другого. Содержание (переменные-члены) и поведение (функции-члены) наследуются и становятся членами другого класса (наследника).

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().