Создаём компьютерную игру
eng   рус

Структуры (Struct) в C++

Предыдущий урок: Функции

В сегодняшнем уроке мы рассмотрим структуры в C++ (Structs). Структуры позволяют определить свой собственный тип данных. В предыдущих урокам мы сталкивались только со стандартными типами данных языка С++: char, float, int... Когда мы начнём рассматривать WinAPI, то увидим, что Microsoft использовала огромное количество структур при написании Windows.

В структурах можно определить несколько переменных для моделирования какого-либо сложного понятия. Например, в нашей программе есть множество юнитов. При этом каждый должен обладать свойствами: размер, сила и скорость. Вот так мы можем описать это в C++ без структур:

int unit_size[10]; int unit_strengths[10]; int unit_speed[10];

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

Структуры C++

struct Unit { int size; int speed; int strength; };

Структуры С++ позволяют построить более адекватную модель сложной (сложнее чем простое число или строка) сущности. Когда мы создаём модель, мы стараемся описать самые важные свойства объекта из реального мира (или абстрактного понятия). Так как в наших примерах мы рассматриваем создание игр, то и примеры будем приводить из этой области. В данном коде мы пытаемся описать единицу (юнит) из какой-то абстрактной игры. В данном случае юнит обладает тремя свойствами - вы сами определяете, что должно быть в структуре.

Структура определяется с помощью ключевого слово struct, после которого идёт имя структуры. Имя может быть любым (стандартный идентификатор C++). В дальнейших уроках все имена структур будут начинаться с заглавной буквы. В WinAPI имена всех структур пишутся в верхнем регистре: RECT, POINT, SIZE и т.д. В фигурных скобках мы описываем разные свойства структуры с помощью объявления переменных. В данном случае, структура Unit будет иметь три свойства: size, speed, strength. Эти переменные называются членами, полями или свойствами структуры. Обратите внимание на точку с запятой после закрывающей фигурной скобки - она обязательна.

Структуры в C++ пришли из языка C. При этом С++ структуры имеют некоторые отличия от оригинала. В следующем уроке мы начнём рассматривать классы и увидим чем структуры в С отличаются от структур в C++.

С++ структуры в памяти

В памяти поля структур располагаются последовательно. Поля size, speed, strength будут расположены рядом. Между ними не будет никаких других данных. Вот как может выглядеть переменная типа Unit в памяти:

0000007F3D3AFAE8 // size 0000007F3D3AFAEC // speed 0000007F3D3AFAF0 // strength

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

Здесь же я хочу обратить внимание на концептуальную разницу между массивами и структурами. И то и другое для компьютера всего лишь множество переменных. В случае массива эти переменные должны быть одного типа, а структуры необходимы для описания более сложных понятий.

Пользовательский тип данных

В C++ структуры являются такими же типами данных как и int, char, double... После определения структуры, её можно использовать как и любой другой тип - создавать структурные переменные.
struct Unit { int size; int speed; int strength; }; Unit u1; Unit u2; Unit units[10];

В последней строке мы создаём массив из десяти структурных переменных. Теперь осталось узнать, как получить доступ к свойствам. Также, мы можем сразу задать значения полям структурных переменных:

Unit u1 = {1,1,1}; Unit units[3] = { {4,4,5}, {2,10,1}, {10,1,25}, };

Значения в фигурных скобках инициализируют поля структурных переменных в том же порядке, в каком поля идут в определении структуры.

Ещё раз повторю, так как это важно: для компьютера это всего лишь числа не имеющие никакого значения. Значение этим числам придаём мы. Мы строим модель какого-то понятия (юнита в данном случае). И мы сами интерпретируем эти значения. Глядя на последний массив мы можем сказать про наши юниты следующее: первый - середнячок, у него все параметры средние; второй - маленький, быстрый, но слабый; последний - большой, медленный, но сильный. Это всего-лишь данные. Когда мы познакомимся с графическим выводом, мы сможем наглядно преподнести эти данные пользователю.

Доступ к полям структурных переменных

Мы можем прочитать и изменить отдельные поля с помощью оператора доступа к члену (member selection operator или member access operator) - точки:

Unit u1; Unit u2; Unit units[10]; u1.strength = 5; units[4].speed = 10;

Сначала мы указываем имя структурной переменной, потом точку, затем имя поля к которому мы хотим получить доступ.

Для структурных переменных, созданных динамически, используется оператор непрямого доступа ->.

Unit* u1 = new Unit; u1->strength = 5;

В отличии от указателей на обычные типы, поля структурных переменных разыменовываются через стрелочку, а не через звёздочку. В остальном их поведение одинаково.

Заключение

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

Комментарии:

No comments yet