Структуры в С++ есть совокупность переменных, объединённых под одним именем.
Структуры помогают группировать связанные переменные вовнутрь одной сущности. Т. е. с помощью структуры можно создать некоторую составную переменную-объект, содержащую в себе группу различных атрибутов.
Пример связанных атрибутов:
Для книги: автор, издательство, язык, название
Для автомобиля: название, салон, расход топлива
Для геометрического круга: радиус, точка центра окружности
Мы группируем набор связанных атрибутов в одной сущности: в книге, в автомобиле, в геометрическом круге и в других, после чего получаем возможность обращаться к этим атрибутам посредством ставшей основной для них сущности. Любая такая сущность, созданная нами путём группирования вовнутрь неё элементов, становится нашим собственным типом данных.
На заметку:
Любой объект, принадлежащий к нашей собственной структуре, является нашим собственным типом данных.
Посмотрим пример простого объявления структуры:
C++
1
2
3
4
5
6
7
8
9
10
structTPoint//Объявили новую структуру TPoint.
{
intx;//Некоторый атрибут
inty;//Некоторый атрибут
};//После описания структуры ставят точку с запятой
intmain()
{
TPointO;//Объявили переменную O типа TPoint
}
Так описывается структура в коде программы. Обратите своё внимание на то, что при объявлении структуры нет круглых скобок:
C++
1
structTPoint()//НЕВЕРНО
И на то, что после закрывающей структуру фигурной скобки стоит точка с запятой:
ВНИМАНИЕ!
Пропущенная точка с запятой является синтаксической ошибкой.
В нашем коде с объявлением структуры мы запихнули в структуру два атрибута. Геометрическа точка в двумерном пространстве состоит из двух составляющих. Эти две составляющие мы объединили в сущность TPoint. Этот TPoint стал нашим собственным типом данных.
Вовнутрь структуры можно группировать сколько угодно сущностей, это количественно не ограничивается никак. Например, для точки из трёхмерного пространства обязательны три атрибута, которые дадут понять кому надо местоположение точки в пространстве. В таком случае структуру можно было бы объявить, например, так:
C++
1
2
3
4
5
structTPoint3D{
doublex;//позиция на оси X
doubley;//позиция на оси Y
doublez;//позиция на оси Z
};//Точка с запятой обязательна!
С объявлением структур мы разобрались, теперь осталось только понять, как их использовать.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//clang использование структур в С++
#include <iostream>
usingnamespacestd;
structTPoint//Объявили новую структуру TPoint.
{
intx;//Некоторый атрибут
inty;//Некоторый атрибут
};//После описания структуры ставят точку с запятой
intmain()
{
TPointO;//Объявили переменную O типа TPoint
O.x=200;//Записываем значения в элементы структуры
O.y=300;
cout<<O.x;//Вытащили из структуры O значение x
cout<<endl;
cout<<O.y;//Вытащили из структуры O значение y
cout<<endl;
cin.get();
}
В общем, в простейшем случае к объекту структуры применяется точка, после которой происходит обращение к названию вытаскиваемого из структуры элемента.
Немного разберём последний показанный код.
У нас была объявлена переменная-объект O, тип которой соответствует структуре TPoint. Внутри структуры было задействовано два атрибута: точка по оси X и точка по оси Y. (int x; int y)
Когда программист обращается к имени переменной, построенной из структуры (в коде к O), он, программист, чаще всего стремится не к использованию целикового объекта, а к конкретному внутреннему атрибуту этого объекта, т.е. лезет внутрь структуры. В простейших структурах такое обращение к атрибутам происходит с помощью точки. Вот, собственно, и вся премудрость.
Поскольку структуры являются нашими собственными типами данных, мы можем создавать много переменных-объектов однотипного характера. Делается это точно так же, как если мы создаём самые обычные переменные.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//clang Работа со структурой Создание нескольких однотипных сущностей
#include <iostream>
usingnamespacestd;
structTPoint//Объявили новую структуру TPoint.
{
intx;//Некоторый атрибут
inty;//Некоторый атрибут
};//После описания структуры ставят точку с запятой
intmain()
{
TPointO;//Объявили переменную O типа TPoint
TPoint T1;// создали другие переменные, тип которых соответствует TPoint
TPoint T2;
O.x=200;//Присваиваете какие-то значения в атрибуты структуры
O.y=300;
T1.x=1000;
T1.y=1111;
T2.x=2222;
T2.y=3333;//Присваиваете какие-то значения в атрибуты структуры
cout<<O.x<<' '<<endl;//Обращаетесь к элементам структуры
cout<<O.y<<' '<<endl;//Обращаетесь к элементам структуры
cout<<endl;
cout<<"T1.x = "<<T1.x<<' '<<endl;//Обращаетесь к элементам структуры
cout<<"T1.y = "T1.y<<' '<<endl;//Обращаетесь к элементам структуры
cout<<endl;
cout<<"T2.x = "<<T2.x<<' '<<endl;//Обращаетесь к элементам структуры
cout<<"T2.x = "<<T2.y<<' '<<endl;//Обращаетесь к элементам структуры
cin.get();
}
Теперь у нас несколько (а именно три) однотипных, но разных сущностей, в которых сгруппировано по две переменные (а именно double x и double y). Т. е. фактически в памяти хранится 6 переменных (3 сущности * 2 внутренние переменные == 6), но мы получаем возможность лёгкого управления подбиранием одной из двух именованных групп и вытаскиванием из неё именованных атрибутов.
.
Мы можем обратиться к T1 и вытаскивать из неё любые внутренние её атрибуты (для каких-то нужных нам модификаций или для чтения значения). T1.x, T1.y
Мы можем обратиться к T2 и вытаскивать из неё любые внутренние её атрибуты (для каких-то нужных нам модификаций или для чтения значения). T2.x, T2.y
Мы можем обратиться к O и вытаскивать из неё любые внутренние её атрибуты (для каких-то нужных нам модификаций или для чтения значения). O.x, O.y
Подобный подход к написанию программы резко повышает читаемость кода и даёт возможность использовать одно имя (внутреннее в структуре), а не несколько имён, как могло бы прийтись писать без структур для одного и того же по природе своей обозначения.
Работать же мы с каждым атрибутом переменной-объекта по типу структура можем точно так же как и с обычными переменными, ведь эти атрибуты и есть обычные переменные. Просто до них нужно немного достукиваться, их надо вытаскивать из структуры.
В описанном примере была создана одна составная переменная, которую мы создали, сгруппировав вовнутрь несколько переменных. Сама по себе структура — это наш собственный тип данных, т. е. её название можно использовать как и любой другой тип данных, приписывать к объявляемой переменной. Создаваемая на основе структуры переменная является объектом структуры. Любой объект структуры даёт нам возможность обращаться к любому своему конкретному внутреннему атрибуту.
C++
1
2
inta;//Переменная a c типом int
MyStructb;//Переменная b с типом MyStruct, где MyStruct любая составленная нами структура
На заметку:
Данные, которые хранятся в объекте одной структуры, могут быть присвоены в любой другой объект той же структуры напрямую.
Здесь всё просто. Поскольку структура — это тип данных, то как и в случае с обычными переменными, типы совпадают — можно присваивать. Но в то же время, если создано несколько разных структур, причём эти структуры полностью совпадают внутренним представлением, то объект одной структуры нельзя напрямую присвоить в объект другой структуры. Несмотря на то, что строение структур может на 100% совпадать, такие структуры считаютя разными типами данных.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//clang Пример присваивания объектов одной структуры
#include <iostream>
usingnamespacestd;
structMyStruct{
intx;
inty;
};
intmain(){
MyStructA,B;//Объявили два объекта: А и В, тип у которых один: MyStruct
A.x=10;//Записали значения в атрибуты объекта А
A.y=20;
B=A;//Присваиваем в объект B все значения из объекта A
cout<<B.x<<'\n';//10
cout<<B.y<<'\n';//20
cin.get();
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Пример с разными структурами
#include <iostream>
usingnamespacestd;
structMyStruct{//Две одинаковые по внутреннеми строению
intx;
inty;
};
structSomeStruct{//считаются разными типами
intx;
inty;
};
intmain(){
MyStructA;//Объявили А, тип которому дали MyStruct
SomeStructB;//Объявили А, тип которому дали SomeStruct
A.x=10;//Записали значения в атрибуты объекта А
A.y=20;
B=A;//Ошибка, разные структуры - разные типы
cout<<B.x<<'\n';//10
cout<<B.y<<'\n';//20
cin.get();
}
Если говорить о присваивании объектов одной и той же структуры друг в друга, то этим присваиванием всё и ограничивается: вы не сможете просто так взять и, например, сложить таким же образом два объекта структуры. Вам нужно будет учить структуру выполнять некоторые операции, если будет необходимо что-то такое проделывать. Такое научение структур пониманию применения некоторых операций называют перегрузкой операций. Эта тема выходит за рамки статьи, в будущем вы познакомитесь с этой интересной особенностью. Просто запомните, что если создано несколько переменных на основе одной и той же структуры, то эти переменные можно присваивать друг в друга вообще без проблем.
На заметку:
Чтобы выводить данные структуры на экран, нужно обращаться ко всем нужным элементам структуры отдельно. Использование операции << без дополнительных усилий не сработает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
usingnamespacestd;
structMyStruct{
intx;
inty;
};
intmain(){
MyStructA,B;//Объявили два объекта: А и В, тип у которых один: MyStruct
A.x=10;//Записали значения в атрибуты объекта А
A.y=20;
cout<<A<<'\n';//Ошибка!
}
Для того, чтобы получить возможность вывода на экран данных объекта структуры путём использования <<, нужно будет учить структуру нужным действиям при применении операции <<. То же самое касается и других операций (умножение, вычитание, чтение с клавиатуры и других). Такое научение структур называется перегрузкой операций.
Пока вы не изучили перегрузку операций, запомните
При попытке доступа к структуре нужно обращаться непосредственно к элементу вовнутрь структуры, а не к структуре как к целому. Исключением пока что можно считать присваивание объектов в объекты, когда все объекты созданы на одной основе, т. е. построены из одной структуры.
Чтобы обратиться к отдельному элементу структуры, нужно прописать этот элемент через точку, после имени переменной-объекта структуры.
У меня есть ещё, что рассказать о структурах. Но я не хочу пока что сильно перегружать читателя, и желаю читателю этой темы безпроблемного освоения данного в статье материала.
5 комментариев на «“Структуры в С++ для начинающих”»
Добрый вечер.Это из первого примера использования структуры:
O.x = 200; //Присваиваете какие-то значения в атрибуты структуры
O.y = 300;
это из пояснения:
«Подобный подход к написанию программы резко повышает читаемость кода и даёт возможность использовать одно имя (внутреннее в структуре), а не несколько имён, как могло бы прийтись писать без структур для одного и того же по природе своей обозначения.»
запись:
int x=200;
int y=300;
Вопрос?Первая запись кроме(как по мне сомнительного)удобства читаемости ,на быстродействие или память влияет?
Напишите самую примитивную программу по вращению треугольника и оцените всё сомнительное удобство.
Ответить на Ваш вопрос точно не могу. Я не специалист и потому не знаю.
Влиять по идее должно, незначительно. Любое обращение через точку это как запрос, т. е. если запустить в цикл на бешеное число повторений, то, может, и можно что-то заподозрить. Но если учитывать, что у современных компиляторов имеются хорошие оптимизаторы, то может, и скорее всего так и есть, и не влиять.
На память влияет выравнивание структур. Не запись, а внутренности структуры.
Спасибо! Понятно растолковали.
Спасибо большое, а то тут уже аврал с бессонной ночью и растерянным взглядом на разработку лаб намечался…
Добрый вечер.Это из первого примера использования структуры:
O.x = 200; //Присваиваете какие-то значения в атрибуты структуры
O.y = 300;
это из пояснения:
«Подобный подход к написанию программы резко повышает читаемость кода и даёт возможность использовать одно имя (внутреннее в структуре), а не несколько имён, как могло бы прийтись писать без структур для одного и того же по природе своей обозначения.»
запись:
int x=200;
int y=300;
Вопрос?Первая запись кроме(как по мне сомнительного)удобства читаемости ,на быстродействие или память влияет?
Напишите самую примитивную программу по вращению треугольника и оцените всё сомнительное удобство.
Ответить на Ваш вопрос точно не могу. Я не специалист и потому не знаю.
Влиять по идее должно, незначительно. Любое обращение через точку это как запрос, т. е. если запустить в цикл на бешеное число повторений, то, может, и можно что-то заподозрить. Но если учитывать, что у современных компиляторов имеются хорошие оптимизаторы, то может, и скорее всего так и есть, и не влиять.
На память влияет выравнивание структур. Не запись, а внутренности структуры.
Спасибо Вам, большое. Вы, излагаете очень доступно и доходчиво.