222 lines
3.9 KiB
Markdown
222 lines
3.9 KiB
Markdown
## Мини-отступление
|
||
|
||
```cpp
|
||
#include <utility>
|
||
C f() {
|
||
C local var;
|
||
|
||
// return local_var - криво
|
||
return std::move(local_var)
|
||
}
|
||
```
|
||
|
||
Благодаря std::move можно не создавать вторую переменную для возвращаемого значения. Входит в стандарт с c++17 и оптимизируется автоматически в c++14.
|
||
|
||
---
|
||
|
||
# Перегрузка операций
|
||
|
||
## Дружеские функции
|
||
|
||
```cpp
|
||
class C {
|
||
int a;
|
||
public:
|
||
...
|
||
friend void f(C &x);
|
||
};
|
||
|
||
void f(C &x) {cout << x.a}
|
||
```
|
||
|
||
функция также может относиться к другому классу
|
||
|
||
## Перегргузка операций
|
||
|
||
Нельзя перегружать:
|
||
|
||
- \#
|
||
- ::
|
||
- ?:
|
||
- .
|
||
- .\*
|
||
- sizeof
|
||
- typeid
|
||
|
||
### Бинарные операции
|
||
|
||
```cpp
|
||
class C{
|
||
double re;
|
||
double im;
|
||
public:
|
||
C (double x = 0.0, double y = 0.0) : re(x), im(y) {}
|
||
bool isEqual(C &obj) {
|
||
return re == obj.re && im == obj.im; // неявная подстановка this->
|
||
}
|
||
|
||
bool operator ==(C &obj) {
|
||
return re == obj.re && im == obj.im;
|
||
}
|
||
|
||
// нужен const, чтобы можно было делать o3 = o1 + 10.0
|
||
C operator+(const C& obj) {
|
||
return C(re + obj.re, im + obj.im);
|
||
} // o3 = o1 + o2
|
||
};
|
||
|
||
void main() {
|
||
C o1, o2, o3;
|
||
|
||
o1.isEqual(o2) == (o1 == o2); // the same
|
||
|
||
o3 = o1 + o2;
|
||
o3 = o1 + 10.0
|
||
|
||
}
|
||
```
|
||
|
||
либо для дальнейшей работы и `o1 = 10.0 + o2` изменим перегрузку операнда:
|
||
|
||
```cpp
|
||
friend C operator+(const C& obj1, const C& obj2) {
|
||
return C(obj2.re + obj1.re, obj2.im + obj1.im);
|
||
}
|
||
```
|
||
|
||
### Унарные операции
|
||
|
||
```cpp
|
||
C operator-() {
|
||
return C(-re, -im);
|
||
} // o3 = -o1
|
||
// !! не перегрузит никак бинарную
|
||
|
||
```
|
||
|
||
Посткремент и инкремент:
|
||
|
||
```cpp
|
||
C& operator++() {
|
||
re++;
|
||
im++;
|
||
return *this;
|
||
}
|
||
|
||
C operator++(int NU) { // not used var
|
||
С tmp(re, im);
|
||
re++;
|
||
im++;
|
||
return tmp;
|
||
}
|
||
|
||
void main() {
|
||
o3 = ++o1;
|
||
o3 = o1++;
|
||
}
|
||
```
|
||
|
||
`o3 = (o1++)++;` не проработает!! (изменит временную переменную)
|
||
|
||
### Перегрузка =, [], ()
|
||
|
||
> не перегружаются как дружественные!
|
||
|
||
```cpp
|
||
C &operator=(const C &obj) {
|
||
re = obj.re;
|
||
im = obj.im;
|
||
|
||
return *this;
|
||
} // по умолчанию так перегружается
|
||
```
|
||
|
||
## Итоговый пример
|
||
|
||
```cpp
|
||
int
|
||
main() {
|
||
string s1("abcd"), s2("qw"), s3;
|
||
s2[1] = 'A';
|
||
s2.print();
|
||
s3 = s1 + s2;
|
||
|
||
s3.print();
|
||
}
|
||
```
|
||
|
||
Итоговый код, чтобы условие выше выполнялось:
|
||
|
||
```cpp
|
||
#include <string.h>
|
||
#include <cstring>
|
||
#include <utility>
|
||
#include <iostream>
|
||
|
||
class string
|
||
{
|
||
int len; // количество памяти
|
||
char* str;
|
||
|
||
public:
|
||
string(const char* s = "") {
|
||
len = strlen(s) + 1;
|
||
str = new char[len];
|
||
strcpy(str, s);
|
||
}
|
||
|
||
char&
|
||
operator[](int n) {
|
||
return str[n];
|
||
}
|
||
|
||
string
|
||
operator+(string s) {
|
||
string tmp;
|
||
tmp.len = s.len + len - 1;
|
||
tmp.str = new char[tmp.len];
|
||
|
||
strcpy(tmp.str, str);
|
||
strcpy(tmp.str + len - 1, s.str);
|
||
|
||
return tmp;
|
||
}
|
||
|
||
string
|
||
operator=(string s) {
|
||
if (s.str == str) {
|
||
return s;
|
||
}
|
||
|
||
delete[] str;
|
||
len = s.len;
|
||
str = new char[len];
|
||
strcpy(str, s.str);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// ~string() { delete[] str; } почему-то с ним не работает (?)
|
||
|
||
void
|
||
print() {
|
||
std::cout << str << " " << len << std::endl;
|
||
}
|
||
};
|
||
```
|
||
|
||
версия присваивания получше:
|
||
|
||
```cpp
|
||
void string::swap(string& a) {
|
||
std::swap(str, a.str);
|
||
std::swap(len, a.len);
|
||
}
|
||
|
||
string& string::operator=(string a) {
|
||
swap(a);
|
||
|
||
return *this;
|
||
}
|
||
```
|