Язык программирования C++ |
Производные типы данных
Структуры
Структуры – это не что иное, как классы, у которых разрешен доступ ко всем их элементам (доступ к определенным атрибутам класса может быть ограничен, о чем мы узнаем в лекции 11). Пример структуры:
struct Record { int number; char name[20]; };
Так же, как и для классов, операция " ." обозначает обращение к элементу структуры.
В отличие от классов, можно определить переменную- структуру без определения отдельного типа:
struct { double x; double y; } coord;
Обратиться к атрибутам переменной coord можно coord.x и coord.y.
Битовые поля
В структуре можно определить размеры атрибута с точностью до бита. Традиционно структуры используются в системном программировании для описания регистров аппаратуры. В них каждый бит имеет свое значение. Не менее важной является возможность экономии памяти – ведь минимальный тип атрибута структуры это байт ( char ), который занимает 8 битов. До сих пор, несмотря на мегабайты и даже гигабайты оперативной памяти, используемые в современных компьютерах, существует немало задач, где каждый бит на счету.
Если после описания атрибута структуры поставить двоеточие и затем целое число, то это число задает количество битов, выделенных под данный атрибут структуры. Такие атрибуты называют битовыми полями . Следующая структура хранит в компактной форме дату и время дня с точностью до секунды.
struct TimeAndDate { unsigned hours :5; // часы от 0 до 24 unsigned mins :6; // минуты unsigned secs :6; // секунды от 0 до 60 unsigned weekDay :3; // день недели unsigned monthDay :6; // день месяца от 1 до 31 unsigned month :5; // месяц от 1 до 12 unsigned year :8; // год от 0 до 100 };
Одна структура TimeAndDate требует всего 39 битов, т.е. 5 байтов (один байт — 8 битов). Если бы мы использовали для каждого атрибута этой структуры тип char, нам бы потребовалось 7 байтов.
Объединения
Особым видом структур данных является объединение. Определение объединения напоминает определение структуры, только вместо ключевого слова struct используется union:
union number { short sx; long lx; double dx; };
В отличие от структуры, все атрибуты объединения располагаются по одному адресу. Под объединение выделяется столько памяти, сколько нужно для хранения наибольшего атрибута объединения. Объединения применяются в тех случаях, когда в один момент времени используется только один атрибут объединения и, прежде всего, для экономии памяти. Предположим, нам нужно определить структуру, которая хранит "универсальное" число, т.е. число одного из предопределенных типов, и признак типа. Это можно сделать следующим образом:
struct Value { enum NumberType { ShortType, LongType, DoubleType }; NumberType type; short sx; // если type равен ShortType long lx; // если type равен LongType double dx; // если type равен DoubleType };
Атрибут type содержит тип хранимого числа, а соответствующий атрибут структуры – значение числа.
Value shortVal; shortVal.type = Value::ShortType; shortVal.sx = 15;
Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя объединение:
struct Value { enum NumberType { ShortType, LongType, DoubleType }; NumberType type; union number { short sx; // если type равен ShortType long lx; // если type равен LongType double dx; // если type равен DoubleType } val; };
Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx ). Однако и обращаться с объединением надо осторожно. Поскольку все три атрибута делят одну и ту же область памяти, изменение одного из них означает изменение всех остальных. На рисунке поясняется выделение памяти под объединение. В обоих случаях мы предполагаем, что структура расположена по адресу 1000. Объединение располагает все три своих атрибута по одному и тому же адресу.
Замечание. Объединения существовали в языке Си, откуда без изменений и перешли в Си++. Использование наследования классов, описанное в следующей главе, позволяет во многих случаях добиться того же эффекта без использования объединений, причем программа будет более надежной.