Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
выш.мат. методичка.DOC
Скачиваний:
32
Добавлен:
13.02.2015
Размер:
1.71 Mб
Скачать

8. Процедурные типы

В Turbo Pascal процедуры и функции можно рассматривать как некоторые параметры и можно использовать переменные, принимающие значение процедуры или функции. С этой цельно вводятся процедурные типы которые указывают, какой вид подпрограммы (процедуру или функцию) можно использовать в качестве параметра и с какими параметрами должны быть эти подпрограммы.

Объявление процедурного типа похоже на заголовок подпрограммы (см п. 10): пишется слово рrосеdurе или function, за которым в круглых скобках записывается список формальных параметров; для функции после списка формальных параметров через двоеточие указывается тип функции. В отличие от заголовка подпрограммы здесь не указывается имя подпрограммы.

Пример

tyре

Рroc1 = рrocedure; {процедура без параметров}

Рrос2 = рrосеdurе (var Х, Y: integer); {процедура с двумя параметрами-переменными целого типа}

Func1 = function(Х: Rеаl): Real; {функция вещественного типа С одним параметром-значением}

Далее можно ввести, переменные этих типов:

var

Р1: Proc1;

Р2: Proc2;

F1: Func1;

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

Существует ряд правил использования подпрограмм в качестве процедурной переменной:

  • они должны компилироваться с ключом компилятора {$F+} или иметь директиву far для получения полного адреса подпрограмм;

  • они не должны быть стандартными процедурами и функциями;

  • они не должны объявляться внутри других процедур и функций;

  • они не должны быть типа inline или interupt (пп. 10.5.5 и 10.5.6).

Пример.

{$F+} рrосеdurе Swap(vаr А, В: Вуtе);

var

Теmp: Вуtе;

begin

Теmp := А; А := В; В := Теmp

еnd;

function Tan(Angle: Real): Real;

begin

Tan:=Sin(Angle)/Cos(Angle) {проверка, что Cos(Angle)<>0, осуществляется в основной программе}

end;

{$F-}

В этом случае процедурным переменным, введенным ранее, можно присвоить значения:

F2:=Swap;

F1:=Tan;

а вызовы Р2(I,J) и F1(X) эквивалентны соответственно Swap(I,J) и Таn(Х).

Так же как и указатель, процедурная переменная занимает 4 байта памяти, в которых помещается полный адрес подпрограммы (поэтому подпрограммы необходимо компилировать с ключом {$Р+}).

Процедурные переменные можно использовать так же, как и переменные других типов: в выражениях (если эта переменная - функция), в виде оператора (если эта переменная - процедура), как компонента другой более сложной переменной, как передаваемый в подпрограмму параметр. Идея единства данных и подпрограмм получила дальнейшее развитие в объектно-ориентированном программировании.

9. Совместимость и преобразование типов данных

Когда в тех или иных операциях или операторах присутствуют данные, относящиеся к различным типам, возникает вопрос о соответствии типов. В связи с этим, говорят об идентичности типов, совместимости типов и совместимости типов для присваивания. Когда возникают проблемы с соответствием типов данных, можно осуществить преобразование тех или иных типов. Эти вопросы и будут рассмотрены в данном разделе.

9.1. Идентичность типов

Идентичность типов требуется от формальных параметров процедур и функций и соответствующих им фактических параметров во время вызова. Два типа Т1 и Т2 идентичны в следующих случаях:

  • Т1 и Т2 - один и тот же идентификатор типа (например, Integer, Rеаl и т.д.);

  • один тип объявляется эквивалентным другому.

Пример

type Т1 = Вооlean; T2 = T1; T3 = Boolean;

Все типы Т1,Т2, ТЗ и Воо1еаn идентичные типы.

type M1 = array[1..5] of Integer;

M2 = array[1..5] of Integer;

Типы М1 и М2 - не идентичные типы. Однако V1 и V2 - переменные идентичных типов:

var V1, V2: аrrау[1..5] оf Integer;

9.2. Совместимость типов

Совместимость типов требуется в выражениях (в том числе и в операциях отношения).

Два типа Т1 и Т2 совместимы в следующих случаях:

  • Т1 и Т2 - один и тот же тип или они идентичны;

  • Т1 и Т2 - вещественные типы;

  • Т1 и Т2 - целые типы;

  • один тип - вещественный, а другой - целый;

  • один тип представляет собой тип-диапазон другого;

  • оба типа являются типами-диапазонами какого-то одного типа;

  • оба типа являются типами-множествами с совместимыми базовыми типами;

  • один тип является строкой, а другой - строкой или символом;

  • один тип - Рointer, а другой - любой тип-указатель;

  • один тип Рсhar, а другой - массив символов. заканчивающийся символом с кодом 0 (только при наличии ключа компилятора {$Х+};

  • оба типа являются указателями, полученными с помощью адресной операции @, примененной к величинам идентичных типов (только при наличии ключа компилятора {$Т+};

  • оба типа -процедурные типы с идентичными типами результатов (для типа-функции), идентичным числом параметром и попарной идентичностью типов этих параметров.

9.3 Совместимость для присваивания

Эта совместимость необходима, когда значение какого-то выражения присваивается переменной, типизированной константе, функции. Если значение объекта типа Т2 присваивается объекту типа Т1, то это возможно в следующих случаях:

  • Т1 и Т2 - идентичные типы и не являются файловыми типами или структурированными типами, содержащими компоненты файлового типа на любом уровне структурирования;

  • Т1 и Т2 - совместимые порядковые типы и значение типа Т2 находится в границах возможных значений объекта типа Т1;

  • Т1 и Т2 - вещественные типы и значение типа Т2 находится в границах возможных значений объекта типа Т1;

  • Т1—вещественный тип, а Т2 - целый тип;

  • Т1 и Т2-строки;

  • Т1- строка, а Т2 - символ;

  • Т1 и Т2 - совместимые типы-множества и все компоненты значения типа Т2 находятся в множестве Т1;

  • Т1 и Т2 - совместимые указатели;

  • Т1 - типа РСhar, а Т2 - строковая константа (только при наличии ключа компилятора {$Х+};

  • Т1 - типа РChar, а Т2 - массив символов, заканчивающийся символом с кодом 0 (только при наличии ключа компилятора {$Х+});

  • Т1 и Т2 - совместимые процедурные типы;

  • Т1 - процедурный тип, а Т2 - процедура или функция с идентичным типом результата, числом параметров и попарной идентичностью типов этих параметров;

  • Т1 и Т2 - объектные типы и Т2 - потомок Т1;

  • • Т1 и Т2 - указатели на объектные типы и Т2 - указатель на потомок типа, на который указывает Т1.

9.4. Преобразование типов

В ряде случаев требуется преобразовать переменную одного типа переменную другого типа. В Turbo Pascal такое преобразование осуществляется сравнительно просто, если переменные обоих типов имеют один и тот же размер. Для этого следует указать идентификатор типа, а за ним в круглых скобках переменную исходного типа. Если новый тип – структурированный, можно в случае необходимости выбрать компоненту в соответствии с общими правилами.

Пример.

type

ВуteRec= record

Lo, Нi: Вуtе

еnd;

Wordrec = record

Low, High: Word

end;

РtrReс = record

Ofs, Seg: Word

end;

ВуtеРtr=^Вуtе;

Vаr

В: Вуtе;

W:Word;

Р: Роinter;

begin.

W:= $1234; {присвоение переменной W значения}

В := ВуteRec(W).Lo {преобразование переменной типа Word в запись из двух байтов и выделение младшего байта}

ВуteRес(W).НI := 0; {преобразование переменной типа Word в запись из двух байтов и запись в старший байт значения 0}

L :=$01234567; {присвоение переменной L значения}

W:=WordRес(L).Lоw; {преобразование переменной типаLongint. в запись из двух слов и выделение младшего слова}

В := ВуtеRес(WordRec(L).Low).Hi; {преобразование переменной типаLongintв запись из двух слов, выделение младшего слова, преобразование его в запись из двух байтов и выделение старшего байта}

В := ВуtеРtr(L); {преобразование переменной типаLongintв указатель и получение значения параметра на который он указывает}

Р :=Рtr($40, $49); {Присвоение указателю Р значения с помощью стандартной функции Рtr}

W := РtrReс(Р).Seg; {преобразование указателя в запись из двух слов выделение второго cлова (фактически адреса сегмента)}

Inc(РtrRес(Р).Ofs,4); {преобразование указателя в запись из двух слов, выделение первого слова (фактически смещения адреса) и увеличение его величины на 4 с помощью стандартной процедурыInc}

Такое преобразование возможно не только, когда исходный и окончательный типы имеют одинаковый размер. Оно возможно также в случае преобразования друг в друга двух порядковых типов (см. п. 3.2), независимо от их размера, а также преобразования параметра без типа (см. п. 10.3.4).