Наследование
2 class Point { double x; double y; Color color; }; class Radius { Point center; double radius; };
3 class Point { double x; double y; Color color; }; class PointText : public Point { std::string text; }
4 1. Велосипед является (is a) транспортным средством? 2. Транспортное средство является велосипедом? -отношение «класс А является классом Б» (IS-A)
5 Наследование – создание новых классов из уже существующих, путем заимствования их данных и методов. Как правило, базовый класс является более общим случаем производного класса. сlass имя_класса : спецификатор_доступа имя_базового_класса { }; Transport Aircraft
6 1. Производный класс наследует все данные и методы базового класса, а также дополняется своими. 2. Доступ к данным и методам базового класса (для класса-потомка и внешнего мира) регулируется спецификаторами доступа. 3. В производном классе можно заново переопределить какие-либо методы.
7 class Transport { float velocityMax; int passengersCountMax; }; class Bicycle : public Transport { int gearsCount; }; class Aircraft : public Transport { int turbinesCount; }
8 Наследование – создание нового класса на основе существующего. Все элементы базового класса заимствуются производным классом. Наследование позволяет использовать уже написанный код базового класса, дополняя его новым кодом производного класса. Достоинства наследования: 1.Исключение повторяющихся фрагментов кода. 2.Упрощается модификация программы. 3.Позволяет изменять поведение классов с закрытым кодом. 4.Структура программы становится более лаконичной. Недостатки наследования: 1.Сильная связность (проблема «хрупких базовых классов»).
9 Button Window Rectangle Square Car Driver File MP3File Circle ColoredCircle Man Student DateTime DailyEvent Композиция vs. Наследование «Содержит» и «Является частным случаем»
10 Конструкторы и наследование Первым всегда вызывается конструктор базового класса! Варианты вызова: 1. Неявный (автоматический) вызов – вызывается конструктор по умолчанию базового класса. 2. Явный вызов – в конструкторе производного класса через название класса- предка (можно передать параметры).
11 class Window { int left; int top; int width; int height; public: Window() : left(0), top(0), width(0), height(0) { } }; class Button : public Window { std::string text; public: Button(std::string text) { this->text = text; } };
12 Window* wnd = new Window(); Button* btn = new Button("OK");
13 Явный вызов конструктора базового класса class Text { std::string text; public: Text(std::string text) : text(text) { } }; class ColoredText : public Text { Color color; public: ColoredText(std::string text, Color color) : Text(text), color(color) { } };
14 Открытые элементы класса доступны всем. Закрытые элементы класса доступны только его методам и друзьям класса. Защищенные элементы базового класса доступны методам и друзьям базового класса, а также методам и друзьям производного класса. Методы производного класса могут обращаться к открытым и защищенным элементам базового класса.
15 Спецификатор наследования В базовом классеВ производном классе public protected private public protected не доступны protectedpublic protected private protected не доступны privatepublic protected private не доступны
16 Классификация наследования (по Тимоти Бадду): 1. Специализация (наследник является специализированной формой предка). 2. Спецификация (дочерний класс реализует поведение, описанное в предке). 3. Конструирование или Варьирование (наследник использует методы предка, но не является его подтипом). 4. Расширение (в потомок добавляют новые методы, расширяя поведение предка). 5. Обобщение (потомок обобщает поведение предка). 6. Ограничение (потомок ограничивает поведение предка).
17 class Matrix { protected: float** m; introws; intcols; public: Matrix(int rows, int cols) { } class MatrixSquare : public Matrix { public: MatrixSquare(int size) : Matrix(size, size) { } float CalcDet(); }
18 Замещающая функция class Man { std::string name; public: std::string ToString() { return name; } };
19 class Student : public Man { int group; public: std::string ToString() { std::stringstream ss; ss
20 Множественное наследование class Istream { std::string read(); } class Ostream { void write(std::string str); } class IOstream : public Istream, public Ostream { } Возможен конфликт имен
21 Порядок вызова конструкторов: 1.Конструкторы базового класса (в порядке объявления при наследовании). 2.Конструкторы объектов-элементов производного класса (в порядке объявления в теле класса). 3.Конструктор производного класса
22 class Foo { public: Foo(): a(b), b(c), c(0){} private: int a; int b; int c; };
23 class A { public: A() {} }; class B { public: B() {} }; class C : public A, public B { public: C(): B(), A() {} };
24 Конфликт имен и его разрешение class A { public: std::string GetTypeName() { return "A"; } }; class B { public: std::string GetTypeName() { return "B"; } }; class C: public A, public B { }; C c; std::cout
25 Виртуальное наследование class A { public: void f(){} }; class B : virtual public A { }; class C : virtual public A { }; class D : public B, public C { };
26 class Base { }; class Child : public Base { }; void main() { Base* pBase = new Child(); Child* pChild = static_cast (pBase); } Понижающее приведение
27 Base* pBase = (Base*)new Alien(); Child* pChild = static_cast (pBase); //? class Alien { };
28 class Base { virtual void f(){} }; class Alien { virtual void ff(){} }; void main() { Base* pBase = (Base*)new Alien(); Child* pChild = dynamic_cast (pBase); if (pChild){ }