КАК МЫСЛИТ UNREAL · ОСНОВЫ C++

Как читать код на C++: минимальный словарь для абсолютного новичка

Эта статья не учит писать код. Она даёт ровно тот минимальный словарь из семи слов — инструкция, переменная, тип, функция, класс, указатель, ссылка — без которого следующая статья энциклопедии (про то, как читать заголовочный файл движка) будет непонятна с первого предложения. Если ты никогда в жизни не писал ни строчки кода — читай эту статью целиком, ничего не пропуская. Если ты уже писал код на любом другом языке — всё равно пройди её: некоторые слова здесь означают в C++ не совсем то, что в других языках.

Более медленный, практический вариант этого же материала

Эта статья — быстрый узнаваемый словарь для чтения кода, а не пошаговое обучение письму. Если хочется того же материала медленнее, с собственноручно написанным кодом и проверяемой практикой на каждом шаге — начальные этапы Learning проходят инструкции, переменные, типы и функции именно в таком темпе, прежде чем переходить к классам и указателям.

01Что это?

Исходный код на C++ — это текстовый файл, который выглядит пугающе только до тех пор, пока в нём не различаешь отдельные, многократно повторяющиеся строительные блоки. Этих блоков немного: инструкция, переменная, тип, функция, класс, указатель, ссылка. Каждый из них — это не абстрактная теория программирования, а конкретный, узнаваемый по внешнему виду кусочек текста. Цель этой статьи — не рассказать всё про C++ (это невозможно в одной статье и не нужно для чтения кода), а дать ровно семь опорных точек, за которые взгляд может зацепиться, когда видит незнакомый файл.

02Почему это существует?

Проблема: одна строка, пять незнакомых слов

Представь, что ты в первый раз в жизни открыл файл с кодом и увидел одну-единственную строку:

float Health;

Для человека, который никогда не программировал, здесь нет ни одного знакомого ориентира. float — это слово из математики? Health — это команда? Зачем в конце точка с запятой, если это не конец предложения на естественном языке? Без ответа на эти вопросы даже одна короткая строка требует полной остановки, а реальные файлы движка — не одна строка, а сотни.

Что именно ломается

Дело не в том, что задача трудная — дело в том, что без базового словаря её вообще не с чем сравнить. Человек, который не знает слова «переменная», не может задать себе следующий, более точный вопрос про эту строку — он застревает на первом же непонятном символе, потому что не знает, к какой категории вещей вообще отнести то, что видит.

Причина: C++ — язык с фиксированным, небольшим набором форм записи

В отличие от естественного языка, где можно сказать одну и ту же мысль тысячей разных способов, у C++ строго ограниченный набор синтаксических форм: программа — это всегда последовательность инструкций, каждая переменная всегда имеет тип, каждая функция всегда объявляется примерно одинаково. Это ограничение — не недостаток, а прямая причина, почему словарь из семи понятий вообще может закрыть подавляющее большинство того, что встретится в реальном файле: форм мало, и они постоянно повторяются.

03Какую проблему решает?

После этой статьи любая строка кода на C++, даже незнакомая по содержанию, распознаётся хотя бы по форме: «это объявление переменной», «это вызов функции», «это указатель». Это не даёт понимания архитектуры Unreal (для этого нужны следующие статьи уровня) — это даёт способность физически не теряться в тексте, различать, где кончается одна мысль автора кода и начинается следующая.

04Как устроено?

Инструкция и точка с запятой

Программа на C++ — это последовательность инструкций (statements): отдельных, законченных действий, которые компьютер должен выполнить одно за другим, сверху вниз (если ничто не меняет этот порядок специально — но об этом не в этой статье). Граница между двумя соседними инструкциями — точка с запятой ;.

🔤 Как это читается на C++

Точка с запятой в C++ играет ту же роль, что точка в конце предложения на естественном языке — она сообщает: «эта мысль закончена, дальше начинается новая». Забытая точка с запятой — одна из самых частых ошибок у тех, кто только начал писать код, потому что компилятор в этом месте не может понять, где кончается одна инструкция и начинается следующая, и сообщает об ошибке — но при чтении кода, что и есть тема этой энциклопедии, точка с запятой, наоборот, самый надёжный ориентир: увидел её — значит, здесь можно мысленно поставить точку и перейти к следующей мысли.

Переменная и тип

Переменная — это именованное место в памяти компьютера, где хранится какое-то значение, которое может меняться по ходу работы программы (отсюда и название — «переменная», в отличие от значения, которое зафиксировано раз и навсегда). У каждой переменной в C++ есть тип — объявление того, какого рода значение в ней вообще может храниться: целое число, дробное число, текст, истина/ложь и так далее. Тип пишется перед именем переменной.

пример — три переменные разных типовC++
int Score;
float Health;
bool bIsAlive;
🔤 Как это читается на C++

int — тип для целых чисел без дробной части (1, 42, -7). float — тип для чисел с дробной частью (3.14, 0.5, -12.75). bool — тип, который может хранить только одно из двух значений: истина (true) или ложь (false) — используется для вопросов вида «да/нет» (например, «жив ли персонаж?»). После типа идёт имя переменной — то, как к этому месту в памяти будет обращаться остальной код. Каждая строка — отдельная инструкция, поэтому каждая заканчивается точкой с запятой.

Тип важен не только для человека, который читает код, — компилятор использует его, чтобы заранее, до запуска программы, отловить бессмысленные операции (например, попытку сложить текст с булевым значением) и понять, сколько именно места в памяти нужно выделить под каждую переменную.

Функция: объявление, реализация, вызов, параметры, возврат

Функция — это именованный, переиспользуемый кусок кода, который выполняет конкретное действие и может быть запущен («вызван») из любого другого места программы, а не только один раз в том месте, где написан. У функции есть три разных, часто путаемых новичками аспекта: объявление — запись формы функции без её содержимого; реализация (или «определение») — тот же заголовок, но уже вместе с реальным кодом внутри фигурных скобок; и вызов — конкретное место в коде, где эту функцию просят выполниться прямо сейчас.

объявление, реализация и вызов одной и той же функцииC++
// Объявление — контракт "такая функция существует", без тела:
int AddDamage(int BaseDamage, int Bonus);

// Реализация — тот же заголовок, но с телом в фигурных скобках:
int AddDamage(int BaseDamage, int Bonus)
{
    return BaseDamage + Bonus;
}

// Вызов — использование функции в другом месте кода:
int TotalDamage = AddDamage(10, 5);  // TotalDamage теперь равен 15
🔤 Как это читается на C++

int AddDamage(int BaseDamage, int Bonus) — первый int здесь означает возвращаемый тип: какого типа значение эта функция отдаёт обратно тому коду, который её вызвал, когда заканчивает работу. Всё, что в круглых скобках — параметры: именованные значения, которые функция получает снаружи при каждом вызове и использует внутри себя как обычные переменные; здесь их два, BaseDamage и Bonus, оба типа int. Слово return внутри тела функции завершает её выполнение и отдаёт указанное после него значение обратно наружу — тому месту, откуда функцию вызвали. В строке вызова AddDamage(10, 5) числа 10 и 5 подставляются на место параметров BaseDamage и Bonus соответственно, в том же порядке, в каком параметры перечислены в объявлении.

Почему это различие важно для чтения, а не только для письма

В реальных файлах движка объявление функции и её реализация почти всегда физически находятся в разных файлах — объявление в заголовочном .h, реализация в .cpp. Если ты видишь строку, заканчивающуюся точкой с запятой сразу после круглых скобок с параметрами, без фигурных скобок с кодом — это объявление, и настоящая логика функции физически находится не здесь, а где-то ещё. Это не «недописанный» код — это нормальная, повсеместная форма записи в C++, и следующая статья энциклопедии разбирает её уже на реальном файле движка.

Класс и объект

Класс — это описание некоторой сущности: какие у неё есть переменные (в контексте класса их называют полями) и какие функции (их называют методами) она умеет выполнять. Класс сам по себе — не готовая вещь, а чертёж. Объект (или экземпляр класса) — это конкретная сущность, построенная по этому чертежу в памяти во время работы программы. Один класс может породить сколько угодно разных объектов, у каждого из которых свои собственные значения полей.

класс как чертёжC++
class FCharacterStats
{
public:
    int Health;
    int Mana;
};
🔤 Как это читается на C++

Слово class открывает описание нового класса, дальше идёт имя, которое ему дали (FCharacterStats). Фигурные скобки { ... } ограничивают тело класса — всё, что относится к его описанию; точка с запятой сразу после закрывающей } обязательна для класса, в отличие, например, от тела функции. Слово public: — секция доступа: всё, что объявлено ниже неё, доступно любому коду, у которого вообще есть доступ к этому классу (у секций доступа есть и более закрытые варианты, но для первого чтения достаточно знать, что они существуют и регулируют, кто может увидеть поле или метод). Внутри — два поля, Health и Mana, каждое со своим типом, объявленные точно так же, как обычные переменные из раздела про переменные, только теперь они принадлежат не одной отдельной инструкции, а целому классу.

Если где-то в коде дальше появится FCharacterStats PlayerOne; и FCharacterStats PlayerTwo; — это будут два отдельных объекта одного и того же класса, и у каждого — собственные, независимые друг от друга значения Health и Mana. Изменение здоровья одного не затронет здоровье другого — точно так же, как два дома, построенных по одному архитектурному чертежу, остаются двумя разными, физически независимыми зданиями.

Указатель и ссылка

Обычная переменная хранит значение напрямую. Указатель хранит не само значение, а адрес — место в памяти компьютера, где это значение на самом деле лежит. Указатель на C++ обозначается звёздочкой * после типа.

обычная переменная vs указательC++
int Score;        // обычная переменная — хранит само число
int* ScorePtr;     // указатель — хранит АДРЕС переменной, а не число
🔤 Как это читается на C++

int* ScorePtr; — звёздочка сразу после типа означает: ScorePtr хранит не целое число напрямую, а адрес в памяти, по которому это число можно найти. Указатель можно сравнить с листком бумаги, на котором написан адрес дома, а не сам дом — по этому листку можно прийти к дому и что-то в нём изменить, но сам листок домом не является. У указателя есть особое значение nullptr — «указатель, который не ведёт никуда»: адрес, по которому заведомо ничего не лежит, и код, использующий указатель, обязан быть готов к этому случаю, прежде чем пытаться пройти по нему.

Ссылка устроена похоже — она тоже не хранит значение напрямую, а обращается к уже существующей переменной, — но в отличие от указателя, обозначается амперсандом &, не может быть «никуда не ведущей» (nullptr для ссылки невозможен) и не требует отдельного шага, чтобы добраться до значения — она ведёт себя как второе имя для уже существующей переменной.

Зачем языку сразу два разных инструмента, делающих на первый взгляд похожую вещь, — вопрос архитектуры кода, а не чтения синтаксиса, и он подробно разбирается в следующих статьях энциклопедии на реальных примерах движка. Здесь достаточно уметь отличить один символ от другого на странице: * — указатель, & — ссылка.

const

Слово const — это обещание компилятору не изменять то, к чему оно относится. Компилятор проверяет это обещание сам: если код всё-таки попытается изменить что-то, помеченное const, сборка проекта остановится с ошибкой ещё до того, как программа вообще запустится.

const у переменнойC++
const int MaxPlayers = 4;  // это значение нельзя изменить нигде дальше в коде

const может стоять в разных местах строки и означать чуть разные вещи — например, у параметра функции он означает «функция не изменит переданное ей значение», а в самом конце объявления метода класса — «вызов этого метода не изменит поля самого объекта». Точный смысл каждого конкретного случая — тема следующих статей, где он будет разбираться прямо на реальном коде движка; здесь важно только не пугаться самого слова и знать, что оно всегда означает какой-то запрет на изменение, а не что-то ещё.

05Когда останавливаться на каждом слове, а когда — читать бегло

Стоит остановиться и разобрать по словарю этой статьи, когда…Можно читать бегло, когда…
Строка использует незнакомую тебе форму записи — ты не можешь с ходу сказать, переменная это, функция или что-то ещёТы уже опознал форму строки (например, «это объявление переменной») — вникать в каждое такое повторение заново не нужно
Ты видишь звёздочку * или амперсанд & рядом с типом и не уверен, что это меняетКомментарий в коде (текст после //) уже объясняет содержательный смысл строки — синтаксис в этом случае вторичен
Функция или класс — часть кода, которую тебе предстоит использовать или изменятьТы просто оцениваешь общий масштаб незнакомого файла (см. следующую статью про чтение заголовков) — на этом этапе важна не каждая строка, а общая структура

Как этим можно злоупотребить

Обратная крайность так же реальна: попытка выучить синтаксис C++ полностью, во всех деталях, прежде чем открыть хоть один реальный файл движка. Язык C++ достаточно большой, чтобы полное его изучение «про запас» заняло значительно больше времени, чем практическое чтение конкретных файлов по мере необходимости — а detали, которые не встретились ни разу за месяц практики, скорее всего, и не понадобятся в ближайшее время. Семь понятий этой статьи покрывают подавляющее большинство того, что реально встречается в заголовках движка на уровне «прочитать и понять форму» — остальное стоит добирать по ходу дела, на конкретных примерах, а не заранее и абстрактно.

06Типичные ошибки

Ошибка новичка: путать объявление функции с вызовом функции

Строки int AddDamage(int BaseDamage, int Bonus); (объявление) и AddDamage(10, 5); (вызов) выглядят похоже — оба содержат имя функции и круглые скобки — но означают принципиально разные вещи: первая описывает форму функции один раз, вторая запускает её выполнение в конкретном месте программы, и таких вызовов в коде может быть сколько угодно. Спутав их, новичок иногда ищет «настоящий код» функции там, где на самом деле стоит лишь очередной вызов — а вызов сам по себе никакой логики не содержит, он лишь обращается к уже существующей реализации.

Ошибка новичка: считать указатель и обычную переменную взаимозаменяемыми

Поскольку int Score; и int* ScorePtr; отличаются на письме одним символом, легко решить, что разница чисто формальная. На деле обращение к значению через указатель требует отдельного шага (нужно «пройти» по адресу, чтобы добраться до самого числа), а сам указатель может оказаться nullptr — и попытка обратиться по нулевому адресу останавливает программу аварийно. Разница на письме в один символ — разница в поведении принципиальная, и в следующих статьях она разбирается на реальных, а не учебных примерах.

Как рассуждает senior

Senior не держит в голове формальную грамматику C++ целиком — он держит в голове ровно тот же самый небольшой набор узнаваемых форм, что разобран в этой статье, и распознаёт их автоматически, не задумываясь, точно так же, как опытный читатель не разбирает по буквам каждое слово в книге на родном языке. Разница между новичком и опытным разработчиком на этом уровне — не объём знаний о языке, а скорость и автоматизм распознавания одних и тех же семи форм, встречающихся вновь и вновь.

07Практика

Задание — назови форму каждой строки
Ниже — четыре строки кода. Для каждой определи: это объявление переменной, объявление функции, вызов функции или указатель?
1) bool bIsAlive;
2) AActor* Target;
3) void TakeDamage(int Amount);
4) TakeDamage(25);
Показать ожидаемый ход рассуждения

(1) Объявление обычной переменной типа bool — имя bIsAlive, звёздочки нет, значит не указатель. (2) Объявление указателя — звёздочка сразу после типа AActor означает, что Target хранит адрес, а не сам объект AActor. (3) Объявление функции без тела — точка с запятой сразу после круглых скобок с параметром, фигурных скобок с кодом нет, значит это контракт, а не реализация. (4) Вызов функции — то же имя TakeDamage, но теперь с конкретным значением 25 вместо описания параметра, и это уже не описание, а команда «выполнить прямо сейчас».

08Частые вопросы

?Нужно ли после этой статьи уметь писать код на C++?

Нет — эта статья и вся эта энциклопедия начинаются с чтения, а не с письма. Умение узнавать переменную, функцию, класс, указатель на странице — необходимый, но самостоятельный навык, который не требует умения написать то же самое с нуля. Письмо кода приходит позже, естественным образом, после того как накопится достаточно прочитанных и понятых примеров.

?Что делать, если в реальном файле движка встретится конструкция, которой нет в этих семи понятиях?

Это ожидаемо и произойдёт почти наверняка — C++ значительно больше семи понятий, и Unreal добавляет поверх ещё и собственные макросы. Правильная реакция — не паниковать и не пытаться заранее выучить весь язык, а либо дочитать соответствующую статью этой энциклопедии, где новая конструкция встретится впервые и будет объяснена на месте (по правилу этого проекта — каждая статья объясняет новую для себя конструкцию сама, не отправляя тебя искать её в другом месте), либо, для одиночного случая, посмотреть значение отдельно и вернуться к чтению.

?Почему в примерах этой статьи не используется реальный код движка?

Потому что цель именно этой статьи — сам язык C++ в чистом виде, без дополнительного слоя макросов и архитектурных решений Unreal, которые иначе отвлекали бы внимание от того, что здесь по-настоящему важно: семи базовых форм. Реальный код движка, размеченный этими же семью понятиями, — тема следующей статьи, «Как читать .h-файл движка».

09Что читатель должен начать замечать

После этой статьи звёздочка и амперсанд рядом с типом перестают быть незначительным штрихом и начинают читаться как явный сигнал «указатель» или «ссылка» — вещи с разным поведением, а не два похожих символа. Точка с запятой без фигурных скобок после круглых скобок функции начинает восприниматься не как обрыв кода, а как узнаваемый признак объявления без реализации. А любая незнакомая строка кода теперь первым делом сортируется по одному и тому же простому вопросу — «это переменная, функция, класс или что-то из этих семи форм» — вместо того чтобы вызывать общее ощущение «слишком сложно, не разберусь».

10Итоги

  • ✔ узнать инструкцию и границу между инструкциями по точке с запятой
  • ✔ отличить переменную и её тип, назвать разницу между int, float и bool
  • ✔ различить объявление функции, её реализацию и вызов — по наличию точки с запятой без тела, тела в фигурных скобках, или конкретных значений вместо параметров
  • ✔ объяснить своими словами разницу между классом как чертежом и объектом как конкретной сущностью, построенной по этому чертежу
  • ✔ по одному символу (* или &) отличить указатель от ссылки на странице кода
  • ✔ понимать, что const — это всегда какой-то запрет на изменение, проверяемый компилятором заранее
  • ✔ по симптому («не понимаю ни слова в этой строке») понять, какого из семи понятий не хватает, вместо общего ощущения «слишком сложно»
💡 Мысли Senior

Семь понятий этой статьи — не начальный, временный этап, который перерастаешь. Это тот же самый словарь, которым опытный разработчик пользуется каждый день, только доведённый до автоматизма. Не старайся запомнить их как список — лучше вернись к этой странице ещё раз после того, как прочитаешь следующую статью на реальном коде движка: второй проход по тем же семи словам, но уже на настоящем примере, закрепляет их значительно быстрее, чем попытка выучить их здесь и сейчас наизусть.

Материал подготовлен для UE C++ Academy. Оригинал статьи — uecppacademy.com. Если материал помог вам разобраться в Unreal Engine — вы можете поддержать развитие проекта.

© 2026 UE C++ Academy. Все права защищены. По вопросам авторских прав или технических проблем — support@uecppacademy.com