7eb0bf1f

Записи с вариантами


Можно очень коротко охарактеризовать основные возможности, которые обеспечивает механизм записей. Главное - это то, что в одной именованной области памяти можно хранить совокупность разнотипных именованных полей, причем имена этих полей специфицируются один раз при определении структурного типа данных. Понятно, что без записей можно обойтись, но с их использованием удобнее и экономичнее программировать.

Идея, которую мы обсудим в этом разделе, тоже в основном относится к повышению уровня удобств программирования. При реальном программировании достаточно часто возникает желание по-разному интерпретировать содержимое одной и той же области памяти в зависимости от конкретных обстоятельств. Хорошим стилем является использование каждой структурной переменной с некоторым объектом предметной области, к которой относится программа. Поля структуры в этом случае содержат требуемые характеристики объекта. Но любой объект может менять свое состояние и соответственно набор характеристик. Поэтому удобно, продолжая использовать ту же область памяти, иметь возможность понимать ее структуру и содержание таким образом, который согласуется с текущим состоянием объекта.

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

Наиболее строгое решение содержится в языках линии Паскаль. В определении всего структурного типа или его завершающей части можно явно указать специальное поле перечисляемого типа (дискриминант), значения которого являются метками соответствующих вариантов типа записи. Для корректного использования переменных такого типа требуется заносить в поле дискриминанта актуальное значение при изменении интерпретации переменной и руководствоваться значением дискриминанта при доступе к содержимому переменной.
Вот пример определения типа записи с вариантами в языке Паскаль: type person = record lname, fname: alfa; birthday: date; marstatus: (single, married); case sex: (male, female) of male: (weight: real; bearded: boolean); female: (size: array[1..3] of integer) end (Считается, что типы данных alfa и date уже определены.) После определения переменной типа person в любой момент можно обращаться и к полям weight и bearded, и к элементам массива size, но корректно это следует делать, руководствуясь значением дискриминанта sex. Более слабый, но эквивалентный по возможностям механизм поддерживается в языках семейства Си. В этих языках существует специальная разновидность типов данных, называемая смесью (union). Фактически, смесь - это запись с вариантами, но без явно поддерживаемого дискриминанта. По нашему мнению, решение о применении такого "облегченного" механизма было принято потому, что использование явно задаваемого дискриминанта в языках линии Паскаль все равно является необязательным, а раз так, то при желании можно просто включить дополнительное поле, значение которого будет характеризовать применимый вариант. Приведенный выше пример можно было бы переписать на языке Си следующим образом: struct person { char lname[10], fname[10]; integer birthday; enum { single, married } marstatus; enum { male, female } sex; union { struct { float weight; integer bearded } male; integer female[3]; } pers; }

Содержание раздела