|
5.1. Типы наследования. Видимость членов классов5.1.1. НаследованиеНаследование - такое отношение между классами, когда один из них наследует (повторяет) структуру и поведение другого. Содержание (переменные-члены) и поведение (функции-члены) наследуются и становятся членами другого класса (наследника). Например, оптические детали линза и зеркало могут быть реализованы, как обычные классы. Но они имеют несколько атрибутов, которые характеризуют их, как оптическую деталь вообще.
Имеет смысл воспользоваться принципом наследования и реализовать, базовый класс Detail. Создание базовых классов и классов-наследников в языке С++ осуществляется следующим образом. class Detail { protected: Position m_p; // положение детали в пространстве double m_D; // диаметр детали };
Базовым может стать любой класс и для этого никаких особых синтаксических конструкций не требуется. При создании классов-наследников необходимо указать базовый класс, от которого осуществляется наследование, а также тип наследования. Таким образом, и Lens и Mirror являются деталями, а параметры детали наследуются, и в результате также являются членами этих классов. 5.1.2. Пример 5.1. Линза и зеркало как оптические детали///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Класс Деталь // Класс Деталь. detal.h // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // проверка на повторное подключение файла #if !defined DETAIL_H #define DETAIL_H ///////////////////////////////////////////////////////////////////////////// // класс Деталь - базовый класс для всех оптических деталей class Detail { protected: // координата детали по оси z double m_z; // диаметр детали double m_D; public: // конструкторы и деструктор Detail(); Detail(double z, double D); ~Detail(); // установить диаметр детали void Set_D(double D); // получить диаметр детали double Get_D() const; // установить координату по оси z void Set_z(double z); // получить координату по оси z double Get_z() const; // печать параметров детали void print() const; }; ///////////////////////////////////////////////////////////////////////////// // установить показатель преломления inline void Detail::Set_D(double D) { m_D=D; } ///////////////////////////////////////////////////////////////////////////// // получить показатель преломления inline double Detail::Get_D() const { return m_D; } ///////////////////////////////////////////////////////////////////////////// // установить координату по оси z inline void Detail::Set_z(double z) { m_z=z; } ///////////////////////////////////////////////////////////////////////////// // получить координату по оси z inline double Detail::Get_z() const { return m_z; } ///////////////////////////////////////////////////////////////////////////// #endif //defined DETAIL_H
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // Класс Деталь. detal.cpp // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; #include "detail.h" ///////////////////////////////////////////////////////////////////////////// // конструктор Detail::Detail() : m_z(0) , m_D(0) { cout<<"constructor Detail()"<<endl; } ///////////////////////////////////////////////////////////////////////////// // конструктор Detail::Detail(double z, double D) : m_z(z) , m_D(D) { cout<<"constructor Detail(z,D)"<<endl; } ///////////////////////////////////////////////////////////////////////////// // деструктор Detail::~Detail() { cout<<"destructor Detail"<<endl; } ///////////////////////////////////////////////////////////////////////////// // печать параметров void Detail::print() const { cout<<"Detail: "<<m_z<<" "<<m_D<<" "; } /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // Класс Линза. lens.h // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // проверка на повторное подключение файла #if !defined LENS_H #define LENS_H #include "detail.h" ///////////////////////////////////////////////////////////////////////////// // класс Линза - наследник от класса Деталь class Lens : public Detail { protected: // радиусы кривизны линзы double m_r1, m_r2; // осевое расстояние double m_d; // показатель преломления double m_n; public: // конструкторы и деструктор Lens(); Lens(double r1, double r2, double d, double n, double z, double D); ~Lens(); // установка показателя преломления void Set_n(double n); // получение показателя преломления double Get_n() const; // установка осевого расстояния void Set_d(double d); // получение осевого расстояния double Get_d() const; // установка 1го радиуса void Set_r1(double r); // получение 1го радиуса double Get_r1() const; // установка 2го радиуса void Set_r2(double r); // получение 2го радиуса double Get_r2() const; // печать параметров линзы void print() const; // вычисление хода луча через линзу void RayTrace(); }; ///////////////////////////////////////////////////////////////////////////// // установка показателя преломления inline void Lens::Set_n(double n) { m_n=n; } ///////////////////////////////////////////////////////////////////////////// // получение показателя преломления inline double Lens::Get_n() const { return m_n; } ///////////////////////////////////////////////////////////////////////////// // установка осевого расстояния inline void Lens::Set_d(double d) { m_d=d; } ///////////////////////////////////////////////////////////////////////////// // получение осевого расстояния inline double Lens::Get_d() const { return m_d; } ///////////////////////////////////////////////////////////////////////////// // установка 1го радиуса inline void Lens::Set_r1(double r) { m_r1=r; } ///////////////////////////////////////////////////////////////////////////// // получение 1го радиуса inline double Lens::Get_r1() const { return m_r1; } ///////////////////////////////////////////////////////////////////////////// // установка 2го радиуса inline void Lens::Set_r2(double r) { m_r2=r; } ///////////////////////////////////////////////////////////////////////////// // получение 2го радиуса inline double Lens::Get_r2() const { return m_r2; } ///////////////////////////////////////////////////////////////////////////// #endif //defined LENS_H
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // Класс Линза. lens.cpp // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; #include "lens.h" ///////////////////////////////////////////////////////////////////////////// // конструктор Lens::Lens() : m_n(1) , m_r1(0) , m_r2(0) , m_d(0) { cout<<"constructor Lens()"<<endl; } ///////////////////////////////////////////////////////////////////////////// // конструктор Lens::Lens(double r1, double r2, double d, double n, double z, double D) : Detail(z, D) , m_n(n) , m_r1(r1) , m_r2(r2) , m_d(d) { cout<<"constructor Lens(r1,r2,d,n)"<<endl; } ///////////////////////////////////////////////////////////////////////////// // деструктор Lens::~Lens() { cout<<"destructor Lens"<<endl; } ///////////////////////////////////////////////////////////////////////////// // печать параметров void Lens::print() const { Detail::print(); cout<<"Lens: "<<m_n<<" "<<m_r1<<" "<<m_r2<<" "<<m_d<<endl; } ///////////////////////////////////////////////////////////////////////////// // вычисление хода луча void Lens::RayTrace() { cout<<"Lens: RayTrace"<<endl; } /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // Класс Зеркало. mirror.h // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// // проверка на повторное подключение файла #if !defined MIRROR_H #define MIRROR_H #include "detail.h" ///////////////////////////////////////////////////////////////////////////// // класс Зеркало - наследник от класса Деталь class Mirror : public Detail { private: // радиус кривизны зеркала double m_r; public: // конструкторы и деструктор Mirror(); Mirror(double r, double z, double D); ~Mirror(); // установка радиуса void Set_r(double r); // получение радиуса double Get_r() const; // печать параметров зеркала void print() const; // вычисление хода луча через зеркало void RayTrace(); }; ///////////////////////////////////////////////////////////////////////////// // установка радиуса inline void Mirror::Set_r(double r) { m_r=r; } ///////////////////////////////////////////////////////////////////////////// // получение радиуса inline double Mirror::Get_r() const { return m_r; } ///////////////////////////////////////////////////////////////////////////// #endif //defined MIRROR_H
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // Класс Зеркало. mirror.cpp // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; #include "mirror.h" ///////////////////////////////////////////////////////////////////////////// // конструктор Mirror::Mirror() : m_r(0) { cout<<"constructor Mirror()"<<endl; } ///////////////////////////////////////////////////////////////////////////// // конструктор Mirror::Mirror(double r, double z, double D) : Detail(z, D) , m_r(r) { cout<<"constructor Mirror(r)"<<endl; } ///////////////////////////////////////////////////////////////////////////// // деструктор Mirror::~Mirror() { cout<<"destructor Mirror"<<endl; } ///////////////////////////////////////////////////////////////////////////// // печать параметров void Mirror::print() const { Detail::print(); cout<<"Mirror: "<<m_r<<endl; } ///////////////////////////////////////////////////////////////////////////// // вычисление хода луча void Mirror::RayTrace() { cout<<"Mirror: RayTrace"<<endl; } /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// // Программирование на языке высокого уровня. Основы языка С++ // Пример 5.1. Линза и зеркало как оптические детали // main.cpp // // http://aco.ifmo.ru/el_books/programming // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; #include "lens.h" #include "mirror.h" ///////////////////////////////////////////////////////////////////////////// void main() { // линза cout<<"test lens:"<<endl; Lens l(100, -100, 10, 1.5, 0, 20); l.print(); // зеркало cout<<endl<<"test mirror:"<<endl; Mirror m(100, 50, 25); m.print(); cout<<endl; } ///////////////////////////////////////////////////////////////////////////// 5.1.3. Последовательность вызова конструкторовПри создании экземпляра класса Lens будет вызван сначала конструктор базового класса (Detail()) и только после этого конструктор класса Lens(). При разрушении экземпляра класса Lens деструкторы будут вызваны в обратном порядке: сначала - деструктор ~Lens(), а затем - ~Detail(). В полном конструкторе (конструкторе копии) наследника обязательно нужно вызывать соответствующий конструктор (полный или копии) базового класса. Если этого не сделать, то компилятор вызовет конструктор по умолчанию для базового класса. Если и его нет, то компилятор выдаст сообщение об ошибке. 5.1.4. Типы наследования. Видимость членов классовВозможно наследование нескольких типов – public, protected и private:
При этом доступ к переменным-членам базового класса будет определяться не только типом видимости членов класса (раздел 4.2.3), но и типом наследования. В таблице показано какой тип доступа будет к членам базового класса, в зависимости от их типа и типа наследования.
5.1.5. Множественное наследованиеМножественное наследование – это наследование свойств одновременно от двух базовых классов. Например, класс Сферическое зеркало может одновременно наследовать свойства от классов Сферическая поверхность и Зеркало. Если класс Child наследуется от двух базовых классов ( Base1 и Base2), то в классе Child будет возможность использования параметров из обоих базовых классов. При создании экземпляра класса Child конструкторы будут вызваны в следующей последовательности: Base1(), Base2() и только после этого конструктор класса Child(). При разрушении экземпляра класса Child деструкторы будут вызваны в обратном порядке: сначала - деструктор ~Child(), затем - ~Base2(), а затем ~Base1().
|