Added 06.md
This commit is contained in:
parent
6228e4a161
commit
5e199a9c83
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;
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue
Block a user