С++, начала ООП Семинар 3 Рябова Анна Сергеевна
Наследование Расширение функциональности без копипаста Не испортим то, что уже работает Дети сохраняют поля и методы родителя
Наследование #include class Movie //Базовый класс { protected: std::string title; int year; public: Movie(std::string newTitle, int newYear) : title(newTitle), year(newYear) { } int getYear() const {return year;} std::string getTitle() const {return title;} void printInfo() { std::cout
Наследование class Serial : public Movie //Производный класс { int numSeries; public: Serial(std::string newTitle, int newYear, int nums) :Movie(newTitle, newYear), numSeries(nums) { } int getNumSeries() const {return numSeries; } void printInfo() { std::cout
Множественное наследование У производного класса может быть несколько базовых class ColouredPoint : public Point, public ColouredItem {... }; Иерархия наследования class Person { … }; class Student: public Person { … }; class 2ndYearStudent: public Student { … }; Student - непосредственный базовый класс (direct base), а Person – косвенный базовый класс (indirect base) 2ndYearStudent
Наследование: уровни доступа class C { private: int a; protected: int b; public: int d; } class CPub: public C { недоступно доступно как protected доступно как public } class CPro: protected C { недоступно доступно как protected доступно как protected } class CPri: private C { недоступно доступно как private доступно как private }
Одноименные поля и методы Используется поле производного класса Доступ к полю базового – через спецификатор доступа :: class Point { public: int x; int y; } class RelativePoint: public Point { public: int x; int direction; int getAbsoluteX() { return Point::x + x; }
Виртуальные функции class Point { public: int x,y; Point(int _x, int _y) : x(_x), y(_y) {}; void show() { // рисуем точку } void hide() { // стираем точку } void move(int new_x, new_y) { // перемещаем из (x,y) в (new_x, new_y) hide(); x=new_x; y=new_y; show(); } }; Методы move одинаковы Circle c(10,10,5); Point p(20,20); c.move(50,50); //Circle::move p.move(70,70); //Point::move class Circle : public Point protected: int r; public: Circle(int _x, int _y, int _r) : r(_r), Point(_x,_y) {}; void show() { // Вариант show для окружности } void hide() { // Вариант hide для окружности } void move(int new_x, int new_y) { hide(); x = new_x; y = new_y; show(); } };
Виртуальные функции class Point { public: int x,y; Point(int _x, int _y) : x(_x), y(_y) {}; virtual void show() { // рисуем точку } virtual void hide() { // стираем точку } void move(int new_x, new_y) { // перемещаем из (x,y) в (new_x, new_y) hide(); x=new_x; y=new_y; show(); } }; Circle c(10,10,5); Point p(20,20); c.move(50,50); //Point::move но с Circle::hide, Circle::show p.move(70,70); //Point::move class Circle : public Point protected: int r; public: Circle(int _x, int _y, int _r) : r(_r), Point(_x,_y) {}; void show() { // Вариант show для окружности } void hide() { // Вариант hide для окружности } };
Виртуальные функции, полиморфизм Указатель на производный класс может быть использован как указатель на базовый класс void moveElement(Point* pt, int delta_x, int delta_y) { pt->move(delta_x, delta_y); } int main() { Circle c; Point p; moveElement(&c); moveElement(&p); return 0; } Полиморфизм - способность объекта вести себя по разному в зависимости от того, как им пользуются. Использовать базовый класс вместо производного нельзя
Чисто виртуальные функции Заранее известно, что метод базового класса вызываться не будет Если есть хоть один виртуальный метод, нельзя создать экземпляр класса Если нет полей, и все метод виртуальные – класс абстрактный class Figure { public: virtual double area() { throw "error!"; } }; class Figure { public: virtual double area()= 0; }; class Circle: public Figure { double radius; public: Circle(double r): radius(r) { } double area() { return * radius * radius; } }; class Square: public Figure { double length; public: Square(double l): length(l) { } double area() { return length * length; } };