- •Що таке композиція?
- •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
- •Обмеження віртуального спадкоємства
- •Коли множинне спадкоємство може бути корисним
- •Переваги використання спадкоємства
- •Спадкоємство і питання проектування
class CTable
{
public:
CTable(std::string const& dbFileName)
{
m_tableFile.Open(dbFileName); std::cout << "Table
constructed\n";
}
virtual ~CTable()
{
m_tableFile.Close();
std::cout << "Table destroyed\n";
}
private:
CFile m_tableFile; };
Output:
Table constructed
Indexed table created
Indexed table destroyed
Table destroyed
class CIndexedTable : public CTable
{
public:
CIndexedTable(std::string const& dbFileName,
std::string const& indexFileName)
:CTable(dbFileName)
{
m_indexFile.Open(indexFileName); std::cout << "Indexed table created\n";
}
~CIndexedTable()
{
m_indexFile.Close();
std::cout << "Indexed table destroyed\n";
}
private:
CFile m_indexFile; };
int main(int argc, char * argv[])
{
CIndexedTable table("users.dat", "users.idx");
return 0;
}
Перевантаження
методів
вУкласіC++ метод спадкоємцевіпохідного класу заміщає собою всі методи батьківського класу з тим же
ім'ям
Кількість і типи аргументів значення не мають
Для виклику методу батьківського класу з методу класу спадкоємця використовується метод Base::
class CBase |
int main(int argc, char * argv[]) |
|||||||||||
{ |
|
|
|
|
|
|||||||
{ |
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
CDerived derived; |
|||||
public: |
|
|
||||||||||
|
|
|
|
|
|
|
||||||
void Print() |
|
|
// вызов метода Print() |
наследника |
||||||||
{ |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
derived.Print("test"); |
|
|
|||
} |
|
std::cout << "CBase::Print\n"; |
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "===\n"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
void Print(std::string const& param) |
|
|
// вызов метода Print() базового класса |
|||||||||
{ |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
derived.CBase::Print(); |
|
|
|
||
} |
|
std::cout << "CBase::Print " << param << "\n"; |
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "===\n“; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
// вызов метода Print базового класса |
|||||
class CDerived : public CBase |
|
|
||||||||||
|
|
derived.CBase::Print("test1"); |
|
|||||||||
{ |
|
|
|
|
|
|
|
|
||||
public: |
|
|
return 0; |
|||||||||
void Print(std::string const& param) |
|
|
||||||||||
} |
|
|
|
|
|
|||||||
{ |
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBase::Print(param); |
|
|
|
|
|
|
|
|
|
|
|
|
Output: |
||||||||||
|
|
std::cout << "CDerived::Print " << param << "\n"; |
|
|
||||||||
|
|
|
|
CBase::Print test |
||||||||
|
|
|
|
|
|
|
|
|||||
} |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
CDerived::Print test |
|||||
}; |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
=== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBase::Print |
||||
|
|
|
|
|
|
|
|
=== |
|
|
|
|
|
|
|
|
|
|
|
|
CBase::Print test1 |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
Завдання - ієрархія геометричних фігур
Розглянемо наступну ієрархію геометричних фігур:
CShape – базовий клас «фігура»
CCircle – клас, що моделює коло
CRectangle - клас, що моделює прямокутник
Кожна фігура володіє наступними властивостями:
Ім'я : «Shape», «Circle» або «Rectangle»Площа фігури
class CShape
{
public:
std::string GetType()const{return "Shape";} double GetArea()const{return 0;}
};
class CRectangle : public CShape
{
public:
CRectangle(double width, double height) :m_width(width), m_height(height){}
std::string GetType()const{return "Rectangle";} double GetArea()const{ return m_width * m_height; }
private:
double m_width; double m_height;
};
class CCircle : public CShape
{
public:
CCircle(double radius):m_radius(radius){} std::string GetType()const{return "Circle";}
double GetArea()const{return 3.14159265 * m_radius * m_radius;} private:
double m_radius;
};
int main(int argc, char * argv[])
{
CCircle circle(10); CRectangle rectangle(20, 10);
std::cout << "Circle area: " << circle.GetArea() << "\n";
std::cout << "Rectangle area: " << rectangle.GetArea() << "\n";
return 0;
}
Output:
Circle area: 314.159
Rectangle area: 200
void PrintShapeArea(CShape const& shape)
{
std::cout << shape.GetType() << " area: " << shape.GetArea() << "\n";
}
int main(int argc, char * argv[])
{
CCircle circle(10);
CRectangle rectangle(20, 10);
PrintShapeArea(circle);
PrintShapeArea(rectangle);
return 0;
}
Output:
Shape area: 0
Shape area: 0
У чому ж проблема?
Проблема в тому, що в даній ситуації при виборі методів, що викликаються, компілятор керується типом послання або покажчика
У нашому випадку відбувається виклик методів класу CShape, оскільки функція PrintShapeArea приймає посилання даного типа
Методи, при виклику яких необхідно керуватися типом об'єкту, мають бути оголошені віртуальними