c++ 1, осень 2015: Объектно-ориентированное...

17
ООП Лекция 8. Объектно-ориентированное программирование Александр Смаль CS центр 14 октября 2015 Санкт-Петербург http://compscicenter.ru 1/17

Upload: cs-center

Post on 10-Jan-2017

2.104 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Лекция 8. Объектно-ориентированноепрограммирование

Александр Смаль

CS центр14 октября 2015Санкт-Петербург

http://compscicenter.ru 1/17

Page 2: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Ещё раз об ООП

Объектно-ориентированное программирование — концпецияпрограммирования, основанная на понятиях объектов иклассов.

Основные принципы:

∙ инкапсуляция,∙ наследование,∙ полиморфизм,∙ абстракция.

Подробнее о принципах проектирования ООП-программ можноузнать по ключевым слову „шаблоны проектирования”.

http://compscicenter.ru 2/17

Page 3: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Как правильно построить иерархию?

Иерархия геометрических фигур:

Shape

Triangle Circle Rectangle

Куда добавить класс Square?

http://compscicenter.ru 3/17

Page 4: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Как правильно построить иерархию?Квадрат — это прямоугольник, у которого все стороны равны.

Shape

Triangle Circle Rectangle

Square

void double_width(Rectangle & r) {r.set_width(r.width () * 2);

}

http://compscicenter.ru 4/17

Page 5: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Как правильно построить иерархию?Прямоугольник задаётся двумя сторонами, а квадрат — одной.

Shape

Triangle Circle Square

Rectangle

double area(Square const& s) {return s.width() * s.width ();

}

http://compscicenter.ru 5/17

Page 6: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Как правильно построить иерархию?

Правильное решение — сделать эти классы независимыми:

Shape

Triangle Circle Rectangle Square

http://compscicenter.ru 6/17

Page 7: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Агрегирование vs наследование

∙ Агрегирование — это включение объекта одного класса вкачестве поля в другой.

∙ Наследование устанавливает более сильные связи междуклассами, нежели агрегирование:

∙ приведение между объектами,∙ доступ к protected членам.

∙ Если наследование можно заменить легко наагрегирование, то это нужно сделать.

Примеры некорректного наследования

∙ Класс Circle унаследовать от класса Point.∙ Класс LinearSystem унаследовать от класса Matrix.

http://compscicenter.ru 7/17

Page 8: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Принцип подстановки Барбары ЛисковLiskov Substitution Principle (LSP)

Функции, работающие с базовым классом, должны иметьвозможность работать с подклассами не зная об этом.

Этот принцип является важнейшим критерием при построениииерархий наследования.

Другие формулировки

∙ Поведение наследуемых классов не должно противоречитьповедению, заданному базовым классом.

∙ Подкласс не должен требовать от вызывающего кодабольше, чем базовый класс, и не должен предоставлятьвызывающему коду меньше, чем базовый класс

http://compscicenter.ru 8/17

Page 9: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Модификаторы при наследованииПри наследовании можно использовать модификаторы доступа:

struct A {};struct B1 : public A {};struct B2 : private A {};struct B3 : protected A {};

Для классов, объявленных как struct, по-умолчаниюиспользуется public, для объявленных как class — private.

Важно: отношение наследования (в терминах ООП) задаётсятолько public-наследованием.

Использование private- и protected-наследованийцелесообразно, если необходимо не только агрегировать другойкласс, но и переопределить его виртуальные методы.

http://compscicenter.ru 9/17

Page 10: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Переопределение private виртуальных методовstruct NetworkDevice {

void send(void * data , size_t size) {log("start sending");send_impl(data , size);log("stop sending");

}...

private:virtual void send_impl(void * data , size_t size){...}

};

struct Router : NetworkDevice {private:

void send_impl(void * data , size_t size) {...}};

http://compscicenter.ru 10/17

Page 11: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Реализация чистых виртуальных методовЧистые виртуальные методы могут иметь определения:

struct NetworkDevice {virtual void send(void * data , size_t size) = 0;...

};

void NetworkDevice ::send(void * data , size_t size) {...

}

struct Router : NetworkDevice {void send(void * data , size_t size) {

// невиртуальный вызовNetworkDevice ::send(data , size);

}};

http://compscicenter.ru 11/17

Page 12: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

ИнтерфейсыИнтерфейс — это абстрактный класс, у которого отсутствуютполя, а все методы являются чистыми виртуальными.

struct IConvertibleToString {virtual ~IConvertibleToString () {}virtual string toString () const = 0;

};

struct IClonable {virtual ~IClonable () {}virtual IClonable * clone () const = 0;

};

struct Person : IClonable {Person * clone() {return new Person (*this );}

};

http://compscicenter.ru 12/17

Page 13: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Множественное наследованиеВ C++ разрешено множественное наследование.

struct Person {};struct Student : Person {};struct Worker : Person {};struct WorkingStudent : Student , Worker {};

Стоит избегать наследования реализаций более чем от одногокласса, вместо этого использовать интерфейсы.

struct IWorker {};struct Worker : Person , IWorker {};struct Student : Person {};struct WorkingStudent : Student , IWorker {}

Множественное наследование — это отдельная большая тема.

http://compscicenter.ru 13/17

Page 14: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Дружественные классыstruct String {

...friend struct StringBuffer;

private:char * data_;size_t len_;

};

struct StringBuffer {void append(String const& s) {

append(s.data_);}void append(char const* s) {...}...

};

http://compscicenter.ru 14/17

Page 15: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Дружественные функцииДружественные функции можно определять прямо внутриописания класса (они становятся inline).

struct String {...friend std:: ostream&

operator <<(std:: ostream & os,String const& s)

{return os << s.data_;

}

private:char * data_;size_t len_;

};

http://compscicenter.ru 15/17

Page 16: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Дружественные методыstruct String;struct StringBuffer {

void append(String const& s);void append(char const* s) {...}...

};

struct String {...friend

void StringBuffer :: append(String const& s);};

void StringBuffer :: append(String const& s) {append(s.data_);

}http://compscicenter.ru 16/17

Page 17: C++ 1, осень 2015: Объектно-ориентированное программирование

ООП

Отношение дружбы

Отношение дружбы можно охарактеризовать следующимиутверждениями:

∙ Отношение дружбы не симметрично.∙ Отношение дружбы не транзитивно.∙ Отношение наследования не задаёт отношение дружбы.∙ Отношение дружбы сильнее, чем отношение наследования.

ВыводСтоит избегать ключевого слова friend, так как оно нарушаетинкапсуляцию.

http://compscicenter.ru 17/17