Структуры
Вектор есть совокупность элементов одного типа; struct является совокупностью элементов (практически) произвольных типов.
Например:
struct address { // почтовый адрес char* name; // имя "Jim Dandy" long number; // номер дома 61 char* street; // улица "South Street" char* town; // город "New Providence" char* state[2]; // штат "N" "J" int zip; // индекс 7974 }
определяет новый тип, названный address (почтовый адрес), состоящий из пунктов, требующихся для того, чтобы послать кому-нибудь корреспонденцию (вообще говоря, address не является достаточным для работы с полным почтовым адресом, но в качестве примера достаточен). Обратите внимание на точку с запятой в конце; это одно из очень немногих мест в C++, где необходимо ставить точку с запятой после фигурной скобки, поэтому люди склонны забывать об этом.
Переменные типа address могут описываться точно также, как другие переменные, а доступ к отдельным членам получается с помощью операции . (точка).
Например:
address jd; jd.name = "Jim Dandy"; jd.number = 61;
Запись, которая использовалась для инициализации векторов, можно применять и к переменным структурных типов.
Например:
address jd = { "Jim Dandy", 61, "South Street", "New Providence", {"N","J"}, 7974 };
Однако обычно лучше использовать конструктор (см. этот пункт). Заметьте, что нельзя было бы инициализировать jd.state строкой "NJ". Строки оканчиваются символом "\0", поэтому в "NJ" три символа, то есть на один больше, чем влезет в jd.state.
К структурным объектам часто обращаются посредством указателей используя операцию ->.
Например:
void print_addr(address* p) { cout << p->name << "\n" << p->number << " " << p->street << "\n" << p->town << "\n" << chr(p->state[0]) << chr(p->state[1]) << " " << p->zip << "\n"; }
Объекты типа структур можно присваивать, передавать как параметры функции и возвращать из функции в качестве результата.
Например:
address current; address set_current(address next) { address prev = current; current = next; return prev; }
Остальные осмысленные операции, такие как сравнение (== и !=) не определены. Однако пользователь может определить эти операции; см. эту главу.
Размер объекта структурного типа нельзя вычислить просто как сумму его членов. Причина этого состоит в том, что многие машины требуют, чтобы объекты определенных типов выравнивались в памяти только по некоторым зависящим от архитектуры границам (типичный пример: целое должно быть выравнено по границе слова) или просто гораздо более эффективно обрабатывают такие объекты, если они выравнены в машине. Это приводит к "дырам" в структуре. Например, (на моей машине) sizeof (address) равен 24, а не 22, как можно было ожидать.
Заметьте, что имя типа становится доступным сразу после того, как оно встретилось, а не только после того, как полностью просмотрено все описание.
Например:
struct link{ link* previous; link* successor; }
Новые объекты структурного типа не могут быть описываться, пока все описание не просмотрено, поэтому
struct no_good { no_good member; };
является ошибочным (компилятор не может установить размер no_good). Чтобы дать возможность двум (или более) структурным типам ссылаться друг на друга, можно просто описать имя как имя структурного типа.
Например:
struct list; // должна быть определена позднее struct link { link* pre; link* suc; link* member_of; }; struct list { link* head; }
Без первого описания list описание link вызвало бы к синтаксическую ошибку.
1 2 3 4 5 6 7 8 9
8 8 8
|