TURBO PASCAL |
Новости
|
Процедурные переменныеПосле определения процедурного типа появляется возможность описывать переменные этого типа. Такие переменные называют проце- дурными переменными. Например, с учетом описаний типа из предыду- щего примера, можно объявить следующие переменные: var P: SwapProc; F: MathFunc; Как и целая переменная, которой можно присвоить значение це- лого типа, процедурной переменной можно присвоить значение проце- дурного типа. Таким значением может быть, конечно, другая проце- дурная переменная, но оно может также представлять собой иденти- фикатор процедуры или функции. В таком контексте описания проце- дуры или функции можно рассматривать, как описание особого рода константы, значением которой является процедура или функция. Нап- ример, пусть мы имеем следующие описания процедуры и функции: procedure Swap(var A,B: integer); var Temp: integer; begin Temp := A; A := B; B := Temp; end. function Tan(Angle: real): real; begin Tan := Sin(Angle) / Cos(Angle); end. Описанным ранее переменным P и F теперь можно присвоить зна- чения: P := Swap; F := Tan; После такого присваивания обращение P(i,j) эквивалентно Swap (i,j) и F(X) эквивалентно Tan(X). Как и при любом другом присваивании, значения переменной в левой и в правой части должны быть совместимы по присваиванию. Процедурные типы, чтобы они были совместимы по присваиванию, должны иметь одно и то же число параметров, а параметры на соот- ветствующих позициях должны быть одинакового типа. Как упомина- лось ранее, имена параметров в описании процедурного типа никако- го действия не вызывают. Кроме того, для обеспечения совместимости по присваиванию процедура и функция, если ее нужно присвоить процедурной перемен- ной, должна удовлетворять следующим требованиям: - Это не должна быть стандартная процедура или функция. - Такая процедура или функция не может быть вложенной. - Такая процедура не должна быть процедурой типа inline. - Она не должна быть процедурой прерывания (interrupt). Стандартными процедурами и функциями считаются процедуры и функции, описанные в модуле System, такие, как Writeln, Readln, Chr, Ord. Чтобы получить возможность использовать стандартную процедуру или функцию с процедурной переменной, вы должны напи- сать для нее специальную "оболочку". Например, пусть мы имеем процедурный тип: type IntProc = procedure(N: integer); Следующая процедура для записи целого числа будет совмести- мой по присваиванию: procedure WriteInt(Number: Integer); far; begin Write(Number); end. Вложенные процедуры и функции с процедурными переменными ис- пользовать нельзя. Процедура или функция считается вложенной, когда она описывается внутри другой процедуры или функции. В сле- дующем примере процедура Inner вложена в процедуру Outer и поэто- му ее нельзя присваивать процедурной переменной: program Nested; procedure Outer; procedure Inner; begin Writeln('Процедура Inner является вложенной'); end; begin Inner; end; begin Outer; end. Использование процедурных типов не ограничивается просто процедурными переменными. Как и любой другой тип, процедурный тип может участвовать в описании структурного типа, что видно из сле- дующих описаний: type GotoProc = procedure(X,Y: integer); ProcList = array[1..10] of GotoProc; WindowPtr = ^WindowRec; Window = record Next: WindowPtr; Header: string[31]; Top,Left,Bottom,Right: integer; SetCursor: GotoProc; end; var P: ProcList; W: WindowPtr; С учетом этих описаний допустимы следующие вызовы процедур: P[3](1,1); W.SetCursor(10,10); Когда процедурной переменной присваивается значение процеду- ры, то на физическом уровне происходит следующее: адрес процедуры сохраняется в переменной. Фактически, процедурная переменная весьма напоминает переменную-указатель, только вместо ссылки на данные она указывает на процедуру или функцию. Как и указатель, процедурная переменная занимает 4 байта (два слова), в которых содержится адрес памяти. В первом слове хранится смещение, во втором - сегмент. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |