From 5e199a9c83e4301d8f83a7e9b1feafb536b19ebb Mon Sep 17 00:00:00 2001 From: thematdev Date: Mon, 9 Oct 2023 20:00:51 +0300 Subject: [PATCH] Added 06.md --- pages/mipt_cxx1/06.md | 196 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 pages/mipt_cxx1/06.md diff --git a/pages/mipt_cxx1/06.md b/pages/mipt_cxx1/06.md new file mode 100644 index 0000000..00c814b --- /dev/null +++ b/pages/mipt_cxx1/06.md @@ -0,0 +1,196 @@ +## 2.7 Type conversions + +`static_cast` -- ключевое слово языка C++ + +```C++ +T x; +static_cast(x); +``` + +С помощью него неявные преобразования можно сделать явно через `static_cast`, +такие как `double -> int, A* -> void*`. + +`reinterpret_cast` -- говорит компилятору трактовать +переменную `x` как переменную типа `U` побитово. То +есть интерпретировать память как будто бы там лежит +другой тип. + +1. `reinterpret_cast` нужно делать от ссылки, например, +`reinterpret_cast(y)`. + +```C++ +long long y; +double &d = reinterpret_cast(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(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` нужно искать __в системе__. + +**Упражнение**. Понять, где у вас лежит `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(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; +} +```