Added 06.md
This commit is contained in:
		
							
								
								
									
										196
									
								
								pages/mipt_cxx1/06.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								pages/mipt_cxx1/06.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
			
		||||
## 2.7 Type conversions
 | 
			
		||||
 | 
			
		||||
`static_cast` -- ключевое слово языка C++
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
T x;
 | 
			
		||||
static_cast<U>(x);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
С помощью него неявные преобразования можно сделать явно через `static_cast`,
 | 
			
		||||
такие как `double -> int, A* -> void*`.
 | 
			
		||||
 | 
			
		||||
`reinterpret_cast` -- говорит компилятору трактовать
 | 
			
		||||
переменную `x` как переменную типа `U` побитово. То
 | 
			
		||||
есть интерпретировать память как будто бы там лежит
 | 
			
		||||
другой тип.
 | 
			
		||||
 | 
			
		||||
1. `reinterpret_cast` нужно делать от ссылки, например,
 | 
			
		||||
`reinterpret_cast<double&>(y)`.
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
long long y;
 | 
			
		||||
double &d = reinterpret_cast<double&>(y); // UB
 | 
			
		||||
d = 3.14;
 | 
			
		||||
std::cout << y << std::endl; // какая-то дичь
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2. По умолчанию это делать нельзя, поэтому в примере выше это UB.
 | 
			
		||||
Это можно делать, например, если есть две структуры в которых
 | 
			
		||||
типы расположены в одном и том же порядке.
 | 
			
		||||
 | 
			
		||||
3. `reinterpret_cast` также можно применять к указателям,
 | 
			
		||||
но только к совместимым
 | 
			
		||||
 | 
			
		||||
4. `reinterpret_cast` не позволяет обходить `const`.
 | 
			
		||||
 | 
			
		||||
Для обхода есть `const_cast`. Он позволяет снять константность.
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
const int c = 5;
 | 
			
		||||
int &cc = const_cast<int&>(c); // также нужно давать ссылку
 | 
			
		||||
cc = 7; // UB
 | 
			
		||||
// и также const_cast от ссылки и указателя это две разные сущности
 | 
			
		||||
std::cout << c << ' ' << cc << std::endl;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Попытка изменить переменную, которая изначально была константой это UB.
 | 
			
		||||
 | 
			
		||||
C-style cast. Всегда бан в программах на C++. По сути он последовательно перебирает все возможные касты, пока он не подойдет. Например,
 | 
			
		||||
вы можете не заметить, как случайно сделаете `const_cast` и словите UB.
 | 
			
		||||
 | 
			
		||||
Байка от Страуструпа: названия кастов специально сделаны слишком большими, чтобы их меньше хотелось писать.
 | 
			
		||||
 | 
			
		||||
Ещё есть `dynamic_cast`, но мы пока про него не говорим.
 | 
			
		||||
 | 
			
		||||
**Стадии сборки**
 | 
			
		||||
 | 
			
		||||
1. Препроцессинг
 | 
			
		||||
 | 
			
		||||
2. Компиляция
 | 
			
		||||
 | 
			
		||||
3. Ассемблирование
 | 
			
		||||
 | 
			
		||||
4. Линковка
 | 
			
		||||
 | 
			
		||||
Препроцессор обрабатывает команды препроцессора по типу `#include, #define, ...`. Это не компиляция, а просто обработка текста.
 | 
			
		||||
 | 
			
		||||
Например, `#include "file"` будет искать файл, `file` в директории файла и в специально указанных путях. Потом он просто заменит эту
 | 
			
		||||
строчку содержимым файла. `#include <header>` говорит, что `header` нужно искать __в системе__.
 | 
			
		||||
 | 
			
		||||
**Упражнение**. Понять, где у вас лежит `iostream`.
 | 
			
		||||
 | 
			
		||||
Далее компилятор переделывает код(уже без директив с решеткой) в ассемблерный код(`.s`). Далее с помощью ассемблера он уже преобразуется
 | 
			
		||||
в объектный файл(уже с машинными инструкциями, `.o`). Далее линкер
 | 
			
		||||
преобразует его в исполняемый файл.
 | 
			
		||||
 | 
			
		||||
В чём разница между `1.cpp -> 1.o` и `a.out`. Линковщик говорит, где нужно искать функции(символы)
 | 
			
		||||
 | 
			
		||||
# 3 Basics of OOP
 | 
			
		||||
 | 
			
		||||
## 3.1 Classes and structures, encapsulation
 | 
			
		||||
 | 
			
		||||
Типы -- классы, данные -- поля классов, операции -- методы классов,
 | 
			
		||||
объекты -- экземпляры классов.
 | 
			
		||||
 | 
			
		||||
Класс можно объявить с помощью ключевого слова `class`, структуру
 | 
			
		||||
с помощью ключевого слова `struct`.
 | 
			
		||||
 | 
			
		||||
Пока мы будем использовать ключевое слово `struct`.
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
struct S {
 | 
			
		||||
    int x; // поле структуры
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    S s;
 | 
			
		||||
    s.x; // обращение к полю x структуры s
 | 
			
		||||
    std::cout << s.x << std::endl; // UB, так как не инициализировано
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
struct S {
 | 
			
		||||
    int x = 1;
 | 
			
		||||
    double d = 3.14;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    S s;
 | 
			
		||||
    std::cout << s.x << std::endl; // ok, x = 1
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Размер структуры равен сумме полей с точностью до _выравнивания_.
 | 
			
		||||
Например `sizeof(S) == 16`, несмотря на то, что `sizeof(int) + sizeof(double) = 12`. Её байты заполнены так: `IIII....DDDDDDDD`, это
 | 
			
		||||
сделано в силу того, что восьмибайтные переменные кладутся по адресам кратным 8. Сам объект `S` тоже хочется положить по адресу кратному
 | 
			
		||||
8, чтобы их можно было класть подряд. Если бы `S` выглядела так: `IIIIDDDDDDDD`, то две такие нельзя было бы поставить подряд.
 | 
			
		||||
 | 
			
		||||
Например, можно сделать `reinterpret_cast<int&>(s)`, тогда мы прочитаем `int` с первых четырех байт `S`.
 | 
			
		||||
 | 
			
		||||
Структуры можно инициализировать агрегатно, `S s{2, 2.718}`.
 | 
			
		||||
 | 
			
		||||
Внутри структур нельзя писать выражения и объявлять пространства имен. Но можно создавать методы и использовать `using`.
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
struct S {
 | 
			
		||||
    ...
 | 
			
		||||
 | 
			
		||||
    void f(int y) {
 | 
			
		||||
        std::cout << x + y << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    S s;
 | 
			
		||||
    s.f(228);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Внутри структур можно использовать методы до того, как они объявлены в коде.
 | 
			
		||||
 | 
			
		||||
Можно объявлять методы вне структуры
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
void S::f(int y) {
 | 
			
		||||
    std::cout << x + y;
 | 
			
		||||
    ff();
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Ключевое слово `this` -- возвращает указатель на объект, в котором мы сейчас находимся.
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
struct S {
 | 
			
		||||
    int x;
 | 
			
		||||
    double d;
 | 
			
		||||
 | 
			
		||||
    void ff(int x) {
 | 
			
		||||
        // x and this->x are not the same
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Можно объявлять структуры внутри структур(inner class).
 | 
			
		||||
 | 
			
		||||
Можно анонимно объявлять структуры
 | 
			
		||||
```C++
 | 
			
		||||
struct {
 | 
			
		||||
    char c;
 | 
			
		||||
} a;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Можно объявить структуру прямо внутри функции(local class).
 | 
			
		||||
 | 
			
		||||
## 3.2 Access modifiers
 | 
			
		||||
 | 
			
		||||
Одним из основных отличий классаот структуры является возможность
 | 
			
		||||
объявить приватное поле/метод. Все поля в структурах по умолчанию публичные, а в классах наоборот приватные, к ним нельзя обратиться
 | 
			
		||||
извне.
 | 
			
		||||
 | 
			
		||||
Ясно, что ошибки доступа проверяются на этапе компиляции.
 | 
			
		||||
Модификаторы доступа можно поменять в классе ключевыми словами `public, private`
 | 
			
		||||
 | 
			
		||||
```C++
 | 
			
		||||
class C {
 | 
			
		||||
public:
 | 
			
		||||
    int x;
 | 
			
		||||
private:
 | 
			
		||||
    int y;
 | 
			
		||||
public:
 | 
			
		||||
    int z;
 | 
			
		||||
private:
 | 
			
		||||
    int t;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
		Reference in New Issue
	
	Block a user