# 09 лекция - C++
(23.04.2022)
## Про шаблоны
> Это не функция! это пример как создать что-либо!
допустим есть a.h файл в котором мы реализуем функцию, и ещё b.h, b.cpp и main.cpp. Допустим мы подклюаем a.h в b.h и main.cpp, при линковке возникает ошибка
## Про структуры в С++
В C++ в структурах можно реализовывать функции (методы)
```c++
struct My
{
int x;
} a, b, c
int myabs (My a) // копирует всю структуру
{
return abs(a.x);
}
int myabs (My *a) // норм
{
return abs(a->x);
}
int myabs (const My &a) // лучший вариант, но не бесплатный, тк лишнее обращение в память (про ссылку)
{
return abs(a.x);
}
```
```c++
struct My
{
int x;
int myabs()
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
} a, b, c;
a.myabs();
b.myabs();
```
> this передается как неявный аргумент метода, но в структуре не храниться!
> методы создаеются с помощью name mangling, и они не принадлежат классу/структуре, мы лишь обьявляем, что они относятся к ним
```c++
struct My
{
int x;
int myabs()
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
const My z = {2};
z.myabs() //не скомпилируется
```
```c++
struct My
{
int x;
int myabs() const // обьявляет что this - указатель на константные данные
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
const My z = {2};
z.myabs() //скомпилируется
```
```c++
struct My
{
int x;
int myabs(int x) {return this->x + x;}
int myabs() const // обьявляет что this - указатель на константные данные
{
return abs(x); // this->x (тоже самое)
// this - это указатель на того, кто вызвал метод
}
}
```
```c++
struct My
{
int x; // рекумедуется называть как m_ (m_x), (как глобальные переменные называть начиная с g_)
static int y; // одна на все структуры такого типа переменная, но видно внутри структуры
// не создает y, надо в одном .cpp в глобальной области сказать
// int My::y;
static int f() {return 2;} // не получает this, но принадлежит только к структуре
int myabs() const
{
return abs(x);
}
}
My::y = 3; // к статическим полям можно оращаться без имени обьескта, а по имени типа
My::f(); // тоже можно
```
## Про перегрузку операторов
```c++
Matrix a, b;
float c;
a.add(b); // а хотелось бы a + b
a.add(c);
```
```c++
My operator+(const My &a, const My &b) //обычная функция (внешняя форма)
// & тк мы не хотим создавать копию
// const чтобы складывалить и константные структуры a + My{5}, например
{
My res;
res.x = a.x + b.x;
res.y = a.y + b.y;
return res;
}
c = a + b; //c = operator+(a, b);
```
```c++
struct My
{
int x;
int y;
My operator+(const My &b) const //метод класса (внутренняя форма)
//const после обьявления чтобы не менять текущий класс
// & тк мы не хотим создавать копию
// const в аргументах чтобы складывалить и константные структуры a + My{5}, например
{
My res;
res.x = x + b.x; // (this.x + b.x)
res.y = y + b.y; // (this.y + b.y)
return res;
}
}
c = a + b; //c = operator+(a, b);
```
> оператор стандартный тип + структура возможно только во внешней форме
> оператор = только во внутренней форме
### Ещё про операторы
```
operator(); //можно перегрузить оператор () и []
operator[];
My a;
a();
a[];
```
Про операторы - `&&` и `||` вычисляется сокращенно, но их тоже можно перегрузить и не будет сокращенного вычисления, тк это уже функции, а не операторы
> сокращенное вычисление - если мы знаем про тип выражения без второго аргумента, то он не будет вычислен
> напрмер, `if(p != NULL && p->x)`
```c++
My operator++(My &x) //++a
{
}
My operator++ (My &x, int) //a++
//можем не указывать имя второму аргументу
//можем указать любой тип в качестве второго аргумента
{
}
```
```c++
My a, b, c;
(a+=b) += c; //хотитим поддерживать
struct My
{
My &operator+=(const My &b)
{
//...
return *this; // & съест * и разъименования на самом деле не произойдет
}
}
```
> В `cout` просто переопределили оператор `<<`
> методы можно разделить на `.h` и `.cpp`
`my.h`
```c++
struct My
{
int x;
int y;
int myabs(); //обьявления
}
```
`my.cpp`
```c++
int My::myabs() //реализация
{
}
```
> методы реализованные в структуре рекомендуются компилятору как встраивымые (`inline`)
## Про конструкторы/деструкторы
```c++
struct My
{
int x;
int y;
My (int a, int b = 0) {x = a; y = b}; // присвоение полям x, y
//My (const My &a) //есть по умолчанию
}
My c(2); //c.x=2, c.y = 0
//My z; //не скомпилируется
```
```c++
struct My
{
int x;
int y;
My () : x(0), y(0); //инициализация полей x, y
}
//My c(2); //не скомпилируется
My z; //c.x = 0, c.y = 0
```
```c++
struct My
{
int x;
int y;
My (int a=1, int b = 0) : x(a), y(b); //инициализация полей x, y
}
My c(2); //c.x = 2, c.y = 0
My z; //c.x = 0, c.y = 0
My z(); //ЭТО ПРОТОТИП ФУНКЦИИ
My z{}; //17 стандарт тоже самое My z;
My z = (); //ЭТО КОНСТРУКТОР
int x(2); //можно теперь писать, вызов конструктора int
```
```
~My() {} //деструктор, вызывается при уничтожениее обьекта, не принимает значений, нельзя перегрузить
```
## Про выделение памяти в С++
```c++
int *p = new int(2); //скалярный оператор
int *arr = new int[10]; //веторный оператор
//...
delete p;
delete[] arr;
```
> `new` и `delete` вызывают конструкторы и деструкторы
> Нет операций изменения размера (`realloc`)
Выделение памяти через malloc с конструкторами и деструкторами
```c++
My *p = (My *) malloc(sizeof(My));
//p->My(); //не скомпилируется
new(p) My(2, 3); //placement new
//просто вызывает конструктор
p->~My(); //деструктор вызывать можно руками
free(p);
```
Проверка на невыделение
```c++
int *p = new int(); //не вернет NULL, бросит эксепшн
#include <new>
unsing namespace std;
int *p = new(nothrow) int; //вернет NULL
```
> в var arg можно передать только double (float неявно приводиться к double)