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
216
217
218
219
220
221
222
223
224
225
226
227
|
# Предефиниране на оператори. Приятелски класове и функции. Mutable член-данни.
## Oператори
### Видове оператори.
в C++ има два вида оператори:
- Унарни (на един аргумент)
- Бинарни (на два аргумента)
### Операторите се характеризират с:
- Приоритет
- Асоциативност
- Позиция на оператора спярмо аргумента - *префиксен*, *инфиксен* и *суфиксен*
### Списъка на операторите в C++:
| Оператор | Асоциативност |
|------------------------------------------------|---------------------------------|
| () [] -> . ++ - - | лявоасоциативен |
| + - ! ~ ++ - - (type)* & sizeof | дясноасоциативен |
| * / % | лявоасоциативен |
| + - | лявоасоциативен|
| << >> | лявоасоциативен|
| < <= > >= | лявоасоциативен|
| == != | лявоасоциативен|
| & | лявоасоциативен |
| ^ | лявоасоциативен |
| \| | лявоасоциативен|
| && | лявоасоциативен|
| \|\| | лявоасоциативен|
| ?: | дясноасоциативен |
| = += -= *= /= %= >>= <<= &= ^= | дясноасоциативен |
### Предефиниране на оператор (пример)
```c++
Complex& Complex::operator+=(const Complex& other)
{
real += other.real;
im += other.im;
return *this;
}
```
Вече може да правим следното:
```c++
int main()
{
Complex c(1,3); //1 + 3i;
Complex c2(10,20) // 10 + 2i;
c += c2 // now c is 11 + 5i
}
```
При предефинирането на оператор **не могат** да се променят *приоритетът*, *асоциативността*, броят и позицията на *аргументите* му.
## Приятелски класове и приятелски функции
Декларират се с на запазената дума **friend** пред прототипа на функцията.
Даденият friend-клас/фунцкия има достъп до всички компоненти на класа.
Т.е. всички членове на класа са public за friend-класовете/функциите приятели.
### Приятелски функции (пример)
```c++
class Complex
{
private:
double real;
double im;
public:
friend double getModulos(const Complex& other);
.
.
.
}
```
```c++
double getModulos(const Complex& other)
{
return sqrt((other.real – other.real) * (other.real – other.real) + (other.im – other.im ) * (other.im – other.im));
}
```
### Mutable (пример)
Спецификатора mutable е приложен само в С++. Той позволява на член на обект да предефинира константността. Така mutable член на const обект не е const и може да бъде изменян.
```c++
struct Test
{
private:
mutable int n;
public:
void f() const
{
n++;
}
};
int main()
{
const Test t;
t.f();
}
```
## Задачи
**Задача 1:**
Реализирайте клас **Nvector**, който ще се използва за работа с математически вектор.
Предефинирайте оператори със следната функционалност:
- Събиране на вектори.
- Изваждане на вектори.
- Умножение на вектор със скалар.
- Проверка дали два вектора са успоредни.
- Проверка дали два вектора са перпендикулярни.
- Взимане на дължина на вектор.
- Достъп до произволен елемент на вектор.
- Вход и изход от потоци.
```c++
int main()
{
Nvector v(4);
cin >> v;
Nvector v2(4);
cin >> v;
Nvector result = v + v2;
cout << result << endl;
}
```
Релизирайте клас двумерната декартова координатна система, която приема 2 вектора, които са нейният базис.
Реализрайте следните функции:
- Връща вектор в базиса по подадени 2 координата.
- По подаден вектор връща координатите му в базиса.
```c++
int main()
{
Nvector v(4);
v[0] = 2;
v[1] = 1;
Nvector v2(4);
v2[0] = 3;
v2[1] = 1;
twoDimCoordSystem s(v1, v2);
cout << s1.getVectorByCoordinates(7, 4); // [26, 11]
cout << s1.getCoordinatesByVector(7, 4); // [5, -1]
cout << result << endl;
}
```
**Задача 2:**
Реализирайте клас **ComplexNumber**, който ще се използва за работа с комплексни числа.
Предефинирайте оператори със следната функционалност:
- Събиране на комплексни числа.
- Изваждане на комплексни числа.
- Умножение на комплексни числа.
- Деление на комплексни числа
- Вход и изход от потоци.
```c++
int main()
{
ComplexNumber c;
cin >> c;
ComplexNumber c2;
cin >> c2;
ComplexNumber result = c2 / c;
cout << result << endl;
}
```
**Задача 3:**
Релизирайте клас - множество(**без повторение**) от думи от малки/главни латински букви и цифри. В колекцията ви търсенето трябва да е с логаритмична сложност.
Предефинирайте оператори:
- += и +. Събиране на две колекции.
- -= и -. От думите на лявата колекция, се премахват тези, които участват в дясната.
- [], който приема дума и връща дали стрингът е в колекцията (очакваме логаритмично време).
- *= за добавяне на дума
- /= за премахване на дума.
- << (поток за изход. Отпечатва всички думи в сортиран вид).
- \>\> (поток за вход. Приема думa, която да се добави в речника).
**Важно!** Копирането на стрингове е бавна операция! Помислете как да организирате данните, за да имате логаритмично търсене на дума и при добавяне на нова дума да правите **минимален брой копирания** на стрингове!
```c++
int main()
{
StringPool dict;
((dict *= "Ivan") *= "Petur") *= "Alex";
std::cout << dict << std::endl; // {Alex, Ivan, Petur}
std::cout << dict["Alex"] << " " << dict["abc"] << std::endl; // 1 0
StringPool dict2;
((dict2 *= "Zebra") *= "Alex");
StringPool result = dict + dict2;
std::cout << result << std::endl; // {Alex, Ivan, Petur, Zebra}
StringPool result2 = dict - dict2;
std::cout << result2 << std::endl; // {Ivan, Petur}
"NewWOrd" >> result2;
result2 /= "NonExistingWord";
std::cout << result2 << std::endl; //{Ivan, NewWOrd, Petur}
"Job" >> result2;
std::cout << result2 << std::endl; //{Ivan, Job, NewWOrd, Petur}
}
```
|