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

Структура в С++ задаётся следующим образом:

1
2
3
struct <имя_структуры> {
  члены (элементы) структуры
};

Например:

1
2
3
struct vec3 {
  double x,y,z;
};

определяет структуру, состоящую из трёх членов типа double.

Определение структуры вводит новый пользовательский тип в программу, который может быть использован так же, как любой встроенный тип.

1
2
3
int counter;
vec3 direction;
double length;

В приведённом примере созданы три переменные – counter типа int, direction типа vec3 и length типа double. Каждая переменная типа vec3 состоит из трёх членов: x, y и z, значения которых уникальны для каждой переменной vec3, также как уникальны значения каждой переменной типа int или double.

Доступ к членам структуры осуществляется посредством оператора . (точка):

1
2
3
direction.x = 0;
direction.y = 0;
direction.z = 1;

Формой записи, используемой при инициализации массива, можно воспользоваться и при инициализации членов структуры:

1:
vec3 normal={0.0,0.0,0.0};

Использование структур

Структуры в С++ используются для логической или физической группировки объектов, имеющих общий контекст. Наиболее очевидным использованием является создание пользовательских типов данных, упрощающих написание, понимание и сопровождение программы.

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

Для более сложных пользовательских типов данных в языке С++ используются классы.

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

1
2
3
4
5
6
7
8
9
struct Point {
  int x,y;
};

Point GetCursorPosition() {
  Point cursor;
  …
  return cursor;
}

В этом случае вызывающая функция будет получать результат типа Point, содержащий два значения – координаты x и y курсора:

1
2
3
4
5
6
void DisplayCursorInfo() {
  Point cursor;
  cursor = GetCursorPosition();
  cout << cursor.x;
  cout << cursor.y;
}

В качестве типов членов структуры могут использоваться ранее объявленные пользовательские типы.

Например, вместо использования структуры вида

1
2
3
4
5
struct Box3 {
  bool visible;
  double x_center, y_center, z_center;
  double x_size, y_size, z_size;
};

Можно воспользоваться предыдущим объявлением структуры vec3 и написать:

1
2
3
4
5
struct Box3 {
  bool visible;
  vec3 center;
  vec3 size;
};

Последний вариант не только компактнее, но и намного понятнее. В этом случае доступ к членам структуры будет осуществляться следующим образом:

1
2
3
4
5
6
7
void Display(const Box3& box) {
  if ( box.visible) {
    cout << “Center: (“ << box.center.x << “,” <<
                           box.center.y << “,” <<
                           box.center.z << “)” << endl;
  }
}

Объекты структур можно присваивать, передавать в качестве аргументов и возвращать в качестве значений функций. Другие операторы (такие как == и != не определены). Объекты структур могут являться элементами массивов.

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

Примеры:

1
2
3
struct Line {
  vec3 pt1,pt2;
};
1
2
3
4
struct Circle {
  vec3 center;
  double radius;
};
1
2
3
struct Plane {
  double a,b,c,d;
};

Типичные ошибки при разработке структур

Наиболее часто встречающейся ошибкой является включение в структуру взаимозависимых данных. То есть таких членов, значения которых могут быть вычислены на основании других членов структуры.

Например, неправильной структурой будет:

1
2
3
4
struct Line {
  vec3   pt1,pt2;
  double length;
};

В данном случае член length может быть вычислен на основании pt1 и pt2. Хранение значение length в структуре нарушает вторую рекомендацию по использованию структур. Кроме расхода памяти для хранения избыточной информации программист получает намного более сложную проблему: необходимость синхронизации данных. При каждом изменении любого из членов структуры придётся пересчитывать значение length.

Более утончённые примеры ошибок:


1
2
3
// Прямоугольник на плоскости
struct Box2 {
  vec2 pt1, pt2, pt3, pt4;
};
 
1
2
3
4
5
// Окружность в трехмерном пространстве
struct CircleIn3D {
  Plane  plane;    // Плоскость, в которой лежит окружность
  vec3   center;
  double radius;
};
Дата последнего обновления 2007 год