Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория 9.doc
Скачиваний:
5
Добавлен:
05.05.2019
Размер:
349.7 Кб
Скачать

2.5. Вариантные структуры данных

2.5.1. Общие понятия

Структура данных программы на языке Pascal (то есть переменные) опи­сывается в одном месте каждого модуля — в разделе описания перемен­ных. Данный раздел начинается ключевым словом Var и специально предназначен для этого. Таким образом, переменные не могут быть вве­дены во время выполнения программы. Еще одна существенная особен­ность представления информации в Pascal — это назначение типа пере­менной на этапе компиляции.

Однако при программировании под Windows довольно часто встречают­ся задачи, в которых переменные должны изменять свой тип во время выполнения программы, соответственно, нельзя на этапе написания про­граммы указать, какого именно типа должна быть та или иная перемен­ная. В основном такие возможности требуются от программы, работаю­щей с базами данных и использующей технологию СОМ.

В Delphi введена поддержка переменных, которые не имеют конкретно­го типа данных на этапе компиляции, а в процессе выполнения програм­мы могут хранить данные разных типов. Такие переменные называются вариантными (англ. Variant — вариантный, различный) и описываются по обычным правилам с указанием в качестве типа данных ключевого сло­ва Variant:

Var

<Назвак/!е

леременной>: Variant;

Во время выполнения программы в вариантных переменных могут хра­ниться данные любого типа, за исключением структурных (записей и статических массивов) и ссылочных (типизированные и нетипизирован-ные указатели, метаклассы и указатели на экземпляры классов7). Также в вариантных переменных не могут находиться значения множественных типов данных. Неинициализированной переменной автоматически при­сваивается специальная константа Unassigned, описанная в модуле

Заметим, что для хранения одних и тех же данных вариантным пере­менным потребуется больше места в памяти, чем типизированным пе­ременным. Кроме того, операции над вариантными переменными вы­полняются несколько дольше. Поэтому применение вариантов оправдано только в тех случаях, когда невозможно обойтись обычными перемен­ными.

Листинг 2.9. Пример описания и использования вариантной переменной

Program UsingVariantsl ; Var

V: Variant;{Описание вариантной переменной,

тип переменной не определен}

S: String; {Описание переменной типа String} Begin

V := 250; {Присвоение значения вариантной переменной V,

переменной назначается целочисленный тип данных;

V := 'It is a STRING' ;

{Присвоение значения вариантной переменной V, переменной назначается строковый тип данных}

S := V; {Строковой переменной присваивается строковое значение вариантной переменной}

End.

2.5.3. Определение типа вариантных переменных

Переменная типа Variant занимает в памяти шестнадцать байт, в ко­торых находится информация о типе данных (код типа), хранящихся в данный момент в данной переменной и сами данные, либо указатель на них. Возможные коды типов данных для вариантных переменных, описанные в модуле System, представлены в табл. 2.4.

Для определения типа данных, хранимых в вариантной переменной, исполь­зуется функция VarType, описанная в модуле Variants в следующем виде:

Function VarType(const V: Variant): TVarType;

Возвращаемое функцией VarType значение имеет тип аналогичный типу Word и содержит информацию о типе данных, а также о том, является ли значение, хранимое в переменной, массивом или указателем. Млад­шие двенадцать бит (три последние шестнадцатеричные цифры) этого значения содержат код типа, соответствующий константам, приведенным в табл. 2.4, а в старших четырех битах могут находиться следующие зна­чения:

♦ нулевое значение $0000 — указывает на то, что данные заявленного типа хранятся непосредственно в вариантной переменной;

♦ значение $2000 (константа varArray модуля System) — указывает на то, что хранимые данные являются массивом элементов, имею­щих тип, определяемый кодом типа данных;

♦ значение $4000 (константа varByRef модуля System) — указывает на то, что хранимые данные являются ссылкой на соответствующий тип данных, определяемый кодом типа данных.

Для выделения части значения, содержащей код типа данных, предус­мотрена константа varTypeMask (значение $0FFF), с помощью которой можно отделить код типа данных от дополнительных признаков:

<Переменная типа Variant> and varTypeMask

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

S := 'Data element type: s;

Case VarType(V) and varTypeMask of

varEmpty: S := S + xThe variant is UnassignecT ;

varNuil: S := S + 'The variant is Null';

Таким образом, если в переменной v находится значение 2 0 0, то после выполнения данного фрагмента программы значением переменной s будет строка 'Data element type: A Byte', если переменной v задать зна­чение 1221.66, то в переменной s будет строка 'Data element type:

Currency floating-point value (type Currency)'. Если же значе­ние переменной V будет строковым, например, '1221.66', то значени­ем переменной S будет такая строка: 'Data element type: Reference to a dynamically allocated string'.

2-5.4. Автоматическое приведение типов

Интересной особенностью вариантных переменных является то, что во время выполнения программы их тип автоматически приводится для соответствия смыслу выражения. Естественно, это правило верно не для всех типов вариантных переменных, а только для тех, в которых хранят­ся числовые (целочисленные и вещественные), строковые, символьные и логические значения.

Допустим, например, что в программе имеется вариантная переменная Vi, которой присвоено значение 2 0 0. После присвоения переменная vi будет целочисленной (иметь тип с кодом varByte):

Vi := 200;

Допустим также, что имеется переменная S типа string. Тогда в резуль­тате выполнения оператора присваивания s := vi, значением перемен­ной s будет строка '200'. Таким образом, во время выполнения опера­тора значение целочисленной переменной будет автоматически переведено в строковый вид.

Более того, возможна и обратная ситуация, когда вариантная перемен­ная строкового типа автоматически переводится в численную форму. Однако именно в таких ситуациях могут возникать ошибки времени выполнения. Рассмотрим пример безошибочного использования вариан­тной переменной (листинг 2.10).

Листинг 2.11. Пример t

Program UsingVariant Var