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