- •Що таке композиція?
- •class CPoint
- •// Колесо
- •// Слайд class CSlide
- •Що таке
- •Термінологія
- •Тварина
- •Варіанти
- •Публічне (відкрите) спадкоємство
- •class CPerson
- •Публічне спадкоємство як
- •CShape
- •CPoint
- •Приватне (закрите) спадкоємство
- •class CIntArray
- •Композиція - переважна
- •class CIntArray
- •Захищене
- •class CIntArray
- •Відмінності між захищеним і відкритим
- •Типи спадкоємства в інших мовах
- •Порядок виклику конструкторів
- •Конструктор класу CEmployee (службовець) оголошений захищеним, аби не допустити безглузде створення абстрактних «службовців»
- •Порядок виклику деструкторів
- •class CTable
- •Перевантаження
- •class CBase
- •Завдання - ієрархія геометричних фігур
- •class CShape
- •int main(int argc, char * argv[])
- •void PrintShapeArea(CShape const& shape)
- •У чому ж проблема?
- •Віртуальні методи
- •class CShape
- •void PrintShapeArea(CShape const& shape)
- •Особливості реалізації віртуальних функцій в
- •Віртуальний
- •class CBase
- •class CBase
- •Підводимо підсумки
- •Абстрактні класи
- •class CShape
- •Інтерфейс
- •class IShape
- •Приведення типів
- •Оператор
- •class CAnimal
- •CMammal const& MakeMammal(CAnimal const & animal)
- •Не зловживайте
- •class CAnimal
- •Множинне
- •IDrawable
- •// інтерфейс об'єктів, які можна намалювати
- •Проблеми, що виникають при множинному спадкоємстві
- •CAnimal
- •//Животное class CAnimal
- •Можливе вирішення даної проблеми - віртуальне спадкоємство
- •//Тварина class CAnimal
- •Обмеження віртуального спадкоємства
- •Коли множинне спадкоємство може бути корисним
- •Переваги використання спадкоємства
- •Спадкоємство і питання проектування
Публічне (відкрите) спадкоємство
Публічне спадкоємство - це
спадкоємство інтерфейсу (спадкоємство типа)
При публічному спадкоємстві відкриті (публічні) поля і методи батьківського класу залишаються відкритими
Похідний клас є підтипом батьківського
Похідний клас служить прикладом відношення «є» (is а)
Похідний клас є об'єктом батьківського
Приклади: «Собака є твариною», «Прямокутник
є замкнутою фігурою»
class CPerson
{
public:
std::string GetName()const; std::string GetAddress()const; int GetBirthYear()const;
private:
};
class CStudent : public CPerson
{
public:
std::string GetUniversityName()const; std::string GetGroupName()const; unsigned GetGrade()const; // год
обучения
};
class CWorker : public CPerson
{
public:
std::string GetJobPosition()const; int GetExperience()const;
};
CPerson
CStudent CWorker
Публічне спадкоємство як
спадкоємство
При публічному спадкоємстві клас-нащадок інтерфейсууспадковує інтерфейс батька
З об'єктами класу-спадкоємця можна звертатися так само як з об'єктами базового класу
Якщо це не так, то, ймовірно відкрите спадкоємство використовувати не слід
Покажчики і посилання на клас-нащадок можуть наводитися до покажчиків і послань на базовий клас
CShape
C2DShape C3DShape
CCircle |
CTriangl |
CCube |
CSphere |
|
e |
||||
|
|
|
void ProcessShape(CShape & shape)
{
...
} |
|
void Test() |
CCircle можна використовувати скрізь, де |
{ |
|
CCircle circle; |
використовується CShape |
ProcessShape(circle);
Покажчик на похідний клас проводиться до
CShape * pShape = &circle; покажчика на базовий
}
CPoint
CCircle
CCylinder
Неправильний хід думок:
«Коло можна отримати, додавши до крапки радіус, а циліндр - додавши до кола висоту»
Неправильний контекст використання відкритого спадкоємства:
Відкрите спадкоємство повинне використовуватися не для того, щоб похідний клас міг використовувати код базового для реалізації
своєї функціональності
Клас-спадкоємець має бути окремим випадком
загальнішої абстрации
Тут:
Коло не є приватним випадком крапки Циліндр не є приватним випадком кола, і, тим більше, крапки
Приватне (закрите) спадкоємство
Приватне спадкоємство - це спадкоємство
реалізації
При приватному спадкоємстві відкриті і захищені поля і методи батьківського класу стають закритими полями і методами похідного
Похідний клас безпосередньо не підтримує відкритий інтерфейс базового, але користується його реалізацією, надаючи власний відкритий інтерфейс
Похідний клас служить прикладом відношення «реалізований на основі» (implemented as)
Похідний клас реалізований на основі батьківського
Приклади: «Клас Stack реалізований на основі класу Array»
class CIntArray
{
public:
int operator[](int index)const; int& operator[](int index); int GetLength()const;
void InsertItem(int index, int value); private:
...
};
class CIntStack : private CIntArray |
||
{ |
Не можна використовувати |
|
public: |
||
відкрите спадкоємство |
||
void Push(int element); |
||
•Стек не є масивом, але |
||
int Pop(); |
||
bool IsEmpty()const; |
користується реалізацією |
|
}; |
масиву |
•До стека не застосовні операції індексованого
Композиція - переважна
альтернатива приватному
спадкоємству
Замість спадкоємства реалізації у багатьох випадках може виявитися краще використовувати
композицію
При композиції новий клас може використовувати декілька екземплярів існуючого класу
Композиція робить класи менш залежними один від одного, чим спадкоємство
Можливі виключення, коли приватне спадкоємство є переважнішим
Необхідно дістати доступ до захищених методів існуючого класу
З точки зору інтерфейсу нового класу - відмінностей немає жодних
class CIntArray
{
public:
int operator[](int index)const; int& operator[](int index);
int GetLength()const;
void InsertItem(int index, int value); private:
...
};
class CIntStack2
{
public:
void Push(int element); int Pop();
bool IsEmpty()const; private:
CIntArray m_items;
};