Website Summary Files Commits Branches @commit @diff @stats
path: root / Sem. 11 / README.md
blob: 26b8428a8fff0861eb91b49393098c90571f03c6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

# Наследяване
## Пример за наследяване

При създаване на нов клас, който има общи компоненти и поведение с вече дефиниран клас, вместо да дефинира повторно тези компоненти и поведение, можем да го обявим за наследник на вече дефинирания.

```c++
class A
{
	.
	. 
	.
public:
	void f()
	{
	.
	.
	.
	}
	
	.
	.
	.	
};
class B : public A
{
	.
	.
	.
};

int main()
{
	B obj;
	obj.f(); // OK!
}
 ```
 При наследяването:
 - Наследяват се член-данните и методите на основните класове
 - Получава се достъп до **някои** от наследените компоненти на основните класове


В нашия пример класът **В е наследник на класа А.** Обекти от класовете изглеждат така:

![enter image description here](https://i.ibb.co/Fshm2LJ/Untitled-Diagram.png)


След като  В е наследник на класа А, то при създаване на обект от тип В се създава обект от тип А, **който е част от обекта** от тип В.


## Видове наследяване
Някои типове наследяване в 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

}
 ```