| Name | Size | |
|---|---|---|
| .. | ||
| Examples | 81 B | log stats plain |
| README.md | 6.0 KiB | log stats plain blame |
Наследяване
Пример за наследяване
При създаване на нов клас, който има общи компоненти и поведение с вече дефиниран клас, вместо да дефинира повторно тези компоненти и поведение, можем да го обявим за наследник на вече дефинирания.
```c++ class A { . . . public: void f() { . . . }
.
.
.
}; class B : public A { . . . };
int main() { B obj; obj.f(); // OK! } ``` При наследяването: - Наследяват се член-данните и методите на основните класове - Получава се достъп до някои от наследените компоненти на основните класове
В нашия пример класът В е наследник на класа А. Обекти от класовете изглеждат така:

След като В е наследник на класа А, то при създаване на обект от тип В се създава обект от тип А, който е част от обекта от тип В.
Видове наследяване
Някои типове наследяване в c++:
- private (по подразбиране)
- protected
- public
Примери: ```c++ class A { public: int x; protected: int y; private: int z; };
class B : public A { // x is public // y is protected // z is not accessible from B };
class C : protected A { // x is protected // y is protected // z is not accessible from C };
class D : private A // 'private' is default for classes { // x is private // y is private // z is not accessible from D }; ```
Подаване като параметри на функции.
Класове-наследници могат да бъдат подавани като параметри на функции, които приемат обекти от базовия клас. Може да се използва функционалността само от базовия клас.
```c++ class A { public: int a; }; class B : public A { public: int b; }; void f(A& obj) { obj.a++; }
void g(A ptr) { (ptr).a++; }
void t(B& obj) { obj.b++; }
int main() { A obj1; B obj2;
f(obj1); //OK!
f(obj2); //OK!
g(&obj1); //OK!
g(&obj2); //OK!
t(obj2); //OK!
//t(obj1)// not ok!
} ```
Конструктори и деструктори при наследяване.
Във всеки конструктор на класа-наследник трябва да се оказва кой конструктор да се извика за базовия клас. Ако не е оказано, ще се извика конструкторът по подразбиране.
c++
class B : public A
{
.
.
.
public:
B(...) : A(...) //some constructor of A.
{
.
.
.
}
};
Деструкторът на наследения клас извиква деструктора на базовия клас.
Копиране при наследяване
При разписване на конструктора за копиране и оператора за присовяване на клас-наследник, трябва експлицитно да извикваме копиране и за базовия клас. ```c++ B::B(const B& other) : A(other) // (copy constructor of A (base class) { copyFrom(other); }
B& B::operator=(const B& other) {
if (this != &other)
{
A::operator=(other); //operator= of A (base class)
free();
copyFrom(other);
}
return *this;
} ```
Разписваме копирането и триенето само ако наследникът ползва необработена динамична памет! Ако няма, то генерираните от компилатора (по горната схема) работят коректно!
Задача 1: Реализирайте класов бар, в който се продават нормални напитки и алкохолни напитки. Трябва да имате функции за зареждане на напитки от бара и взимане на напитка от бара. При зареждането се посочва и броят на артикулите, които се зареждат. Ако не се каже брой - зарежда се 1 артикул.
При взимането на напитка от бара: Избира се тип (нормална или алкохолна) и се връща най-отдавна заредената в бара. Във всеки момент трябва да могат да се взимат статистика за бара - брой продадени артикула oт всеки тип и сумарно продадени мл.
Напитката има име (низ с произволна дължина, само от латински символи, в който първият символ е главен), количество (в мл [200, 1000]), а алкохолната напитка има име (низ с произволна дължина, само от латински символи, в който първият символ е главен), количество (в мл [200, 1000]) и процент алкохол [5, 98].
Примерен интерфейс: ```c++
int main() { Bar b;
b.addDrink("Coke", 330, 2); //2x Coca cola 330 ml
b.addDrink("Fanta", 500); //1x Fanta 500 ml
b.addAlocoholDrink("Zagorka", 500, 5); //1x Zagorka, 5% alc, 500 ml
b.getAcloholDrink(); // Zagorka
b.getDrink() // Coke
b.getDrink() // Coke
b.getDrink() // Fanta
b.getAlocholDrinksSold(); // 1
b.getDrinksMlSold(); // 830
} ```
