Pas-pg.dos/Tpw8 icon

Pas-pg.dos/Tpw8



НазваниеPas-pg.dos/Tpw8
Дата конвертации28.08.2012
Размер43.5 Kb.
ТипДокументы
1. /Pas-pg.dos/Cont.txt
2. /Pas-pg.dos/Tpw1.txt
3. /Pas-pg.dos/Tpw10.txt
4. /Pas-pg.dos/Tpw11.txt
5. /Pas-pg.dos/Tpw12.txt
6. /Pas-pg.dos/Tpw13.txt
7. /Pas-pg.dos/Tpw14.txt
8. /Pas-pg.dos/Tpw15.txt
9. /Pas-pg.dos/Tpw16.txt
10. /Pas-pg.dos/Tpw17.txt
11. /Pas-pg.dos/Tpw18.txt
12. /Pas-pg.dos/Tpw19.txt
13. /Pas-pg.dos/Tpw2.txt
14. /Pas-pg.dos/Tpw20.txt
15. /Pas-pg.dos/Tpw21.txt
16. /Pas-pg.dos/Tpw22.txt
17. /Pas-pg.dos/Tpw23.txt
18. /Pas-pg.dos/Tpw24_1.txt
19. /Pas-pg.dos/Tpw24_2.txt
20. /Pas-pg.dos/Tpw3.txt
21. /Pas-pg.dos/Tpw4.txt
22. /Pas-pg.dos/Tpw5.txt
23. /Pas-pg.dos/Tpw6.txt
24. /Pas-pg.dos/Tpw7.txt
25. /Pas-pg.dos/Tpw8.txt
26. /Pas-pg.dos/Tpw9.txt
27. /Pas-pg.dos/Tpwa.txt
28. /Pas-pg.dos/Tpwb.txt
29. /Pas-pg.dos/Tpwin.txt
1╛лRП XXXXXC:\WORD55\NORMAL.STYSITIZENYXXX^Глава 8. Процедуры и функции
Процедуры и функции позволяют включать в основной программный блок дополнительные блоки. Каждое описание процедуры или функции содержит заголовок, за которым следует программный блок. Процедура активизируется с помощью оператора процедуры. Функция активизируется при вычислении выражения, содержащего вызов функции и возвращаемое функцией значение подставляется в это выражение. 
     В данной главе обсуждаются различные способы описания процедуры или функции и их параметры. 
                        Описания процедур

     Описание процедуры позволяет связать идентификатор с процедурным блоком.
Процедуру можно затем активизировать с помощью оператора процедуры. ┌───────────┐ ╒═╕ ┌────────────────┐ ╒═╕ описание ──│ заголовок ├─│;├─│ тело процедуры ├─│;├─────── процедуры │ процедуры │ ╘═╛ └────────────────┘ ╘═╛ └───────────┘ ╒═══════════╕ ┌─────────────┐ заголовок -│ procedure ├─│идентификатор├──┬───────────────── процедуры ╘═══════════╛ └─────────────┘ │  ┌───────┘ │ │ ┌────────────────┐ │ │ │ список │ │ └─┤ формальных │─┘ │ параметров │ └────────────────┘ ┌────────────────────┐ тип параметра ───────│ идентификатор типа ├────┬────  └────────────────────┘ │ │ ╒════════╕ │ └───────────┤ строка │─────────┘ ╘════════╛ ┌──────┐ тело ┌─────────────────────────────┬─│ блок │────── процедуры │  │ └──────┘  │ ╒════════════╕ ╒═══╕ │ │ │ ├──│ interrupt ├───│ ; ├─┘ │ │ │ ╘════════════╛  ╘═══╛ │ │ │ ╒════════════╕ │ │ │ ├──│ near ├─┤ │ │ │ ╘════════════╛ │ │ │ │ ╒════════════╕ │ │ │ ├──│ far ├─┤ │ │ │ ╘════════════╛ │ │ │ │ ╒════════════╕ │ │ │ ├──│ export ├─┘ │ │ │ ╘════════════╛ │ │ │ ┌────────────────┘ │ │ │ ╒═════════╕ │ │ ├─│ forward ├───────────────│ │ │ ╘═════════╛ │ │ │ ╒══════════╕ │ │ ├─│ external ├──────────────│ │ │ ╘══════════╛ │ │ │ ┌──────────────┐ │ │ └──│ блок asm ├─────────│ │ └──────────────┘ │ │ ╒══════════════════════════╕ │ └────│ директива inline ├─────────┘ ╘══════════════════════════╛ В заголовке процедуры указывается имя процедуры и описывается список формальных параметров (если он присутствует). Примечание: Синтаксис для списка формальных параметров показан далее в этой главе в разделе "Параметры". Процедура активизируется с помощью оператора процедуры, в котором содержатся имя процедуры и необходимые параметры. Операторы, которые должны выполняться при запуске процедуры, содержатся в операторной части модуля процедуры. Если в содержащемся в процедуре операторе внутри модуля процедуры используется идентификатор процедуры, то процедура будет выполняться рекурсивно (будет при выполнении обращаться сама к себе). Приведем пример описания процедуры: procedure NumString(N: integer; var S: string); var V: integer; begin V := Abs(N); S := ''; repeat S := Chr(N mod 10 + Ord('0')) + S; N := N div 10; until N = 0; if N < 0 then S := '-' + S; end; Описания near и far Турбо Паскаль поддерживает две модели вызова процедур - ближнюю (near) и дальнюю (far). С точки зрения объема программы и скорости выполнения ближняя модель вызова более эффективна, но с ней связаны ограничения: процедуры типа near могут вызываться только в том модуле, где они описаны. Процедуры же с дальним типом вызова можно вызывать из любого модуля, но они несколько менее эффективны. Примечание: О вызовах ближнего и дальнего типа рассказывается в Главе 18 "Вопросы управления". На основе описания процедуры Турбо Паскаль будет автоматически выбирать правильную модель вызова. Для процедур, описанных в интерфейсной части модуля (interface), используется дальняя модель вызова - их можно вызывать из других модулей. Процедуры, описанные в секции реализации модуля (implementation), имеют ближний тип вызова. Вызываться они могут только из программ данного модуля. Для некоторых специальных целей может потребоваться использовать модель с дальним типом вызова. Например, в оверлейных задачах обычно требуется, чтобы все процедуры и функции имели дальний тип вызова. Аналогично, если процедура или функция присваивается процедурной переменной, то она также должна использовать дальний тип вызова. Чтобы переопределить автоматический выбор модели вызова компилятором, можно использовать директиву компилятора {$F+}. Процедуры и функции, компилируемые в состоянии {$F+}, всегда будут иметь дальний тип вызова (far), а в состоянии {$F-} компилятор автоматически выбирает корректную модель. По умолчанию используется директива {$F-}. Чтобы задать конкретную модель вызова, в описании процедуры перед ее блоком можно указать директиву near или far. При наличии такой директивы она переопределяет директиву $F компилятора и автоматический выбор модели вызова. Описания export Директива export делает процедуру или функцию "экспортируемой", принудительно используя дальний тип вызова и подготавливая подпрограмму для экспорта путем генерации специального кода входа и выхода. В Windows требуется, чтобы процедуры и функции были экспортируемыми в следующих случаях: - процедуры и функции, которые экспортируются DLL (динамически компонуемой библиотекой); - процедуры и функции вызова. В Главе 10 "Динамически компонуемые библиотеки" описывается, как можно экспортировать процедуры и функции в DLL. Заметим, что даже если процедура или функция компилируется с директивой export, фактический экспорт процедуры или функции не происходит до тех пор, пока подпрограмма не указывается в операторе exports библиотеки. Процедуры и функции вызова - это те процедуры и функции в вашей прикладной программе, которые вызываются не вашей прикладной программой, а Windows. Процедуры и функции вызова компилируются с директивой export, но их не нужно указывать в операторе exports. Приведем некоторые общие примеры процедур и функций вызова: - процедуры Windows; - диалоговые процедуры; - перечислимые процедуры вызова; - процедуры описания памяти; - специальные процедуры Windows (фильтры). Описания interrupt В описании процедуры перед блоком операторов может указыватся директива прерывания (interrupt). Процедура в этом случае рассматривается, как процедура прерывания. Примечание: Полное описание процедур прерывания приводится в Главе 18 "Вопросы управления". В данный момент отметим, что процедуры обработки прерывания нельзя вызывать с помощью операторов процедуры, и что в каждой из них задается список параметров, который обязательно должен иметь следующий вид: procedure MyInt(Flags,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP : word); interrupt; Вместо блока операторов в описании процедуры или функции можно записать опережающее описание (описание forward), внешнее описание (описание external) или описание inline. Описание forward Описание процедуры, содержащее вместо блока операторов директиву forward, называется опережающим описанием. В каком-либо месте после этого описания с помощью определяющего описания должна определяться процедура. Определяющее описание - это описание, в котором используется тот же идентификатор процедуры, но опущен список формальных параметров и в которое включен блок операторов. Описание forward и определяющее описание должны присутствовать в одной и той же части описания процедуры и функции. Между ними могут описываться другие процедуры и функции, которые могут обращаться к процедуре с опережающим описанием. Таким образом возможна взаимная рекурсия. Опережающее описание и определяющее описание представляют собой полное описание процедуры. Процедура считается описанной с помощью опережающего описания. Приведем следующий пример опережающего описания: procedure Walter(m,n : integer); forward; procedure Clara(x,y : real); begin . . . end; procedure Walter; begin . . Clara(8.3,2.4); . . end; Определяющее описание процедуры может быть внешним описанием (external). Однако, оно не может быть описанием inline или другим опережающим описанием. Определяющее описание также не может содержать директиву interrupt. Опережающие описания не допускаются в интерфейсной части модуля. Описания external Описания external позволяют компоновать отдельно скомпилированные процедуры и функции, написанные на языке Ассемблера. С помощью команды "$L имя_файла" для внешней программы должны быть установлены связи с программой или модулем на языке Паскаль. Примечание: Более детальное описания компоновки с программой на языке Ассемблера содержится в Главе 23. Приведем следующие примеры описаний внешних процедур: procedure MoveWord(var source,dest; count: longint); external; procedure MoveLong(var source,dest; count: longint); external; procedure FillWord(var dest,data: integer; count: longint); external; procedure FillLong(var dest,data: integer; count: longint); external; {$L BLOCK.OBJ} Директиву external можно также использовать для импорта процедур и функций из DLL (динамически компонуемой библиотеки). Например, слкедующее описание external импортирует функцию с именем GlobalAlloc из библиотеки DLL с именем 'KERNEL' (ядро Windows). function GlobalAlloc(Flags: Word; Bytes: LongInt: THandle; far; external 'KERNEL' index 15; Директива external занимает место описания и операторной части импортируемой процедуры или функции. Импортируемые процедуры и функции должны использовать дальний тип вызова, задаваемый директивой far или директивой компилятора {$F}. Кроме этого требования импортируемые процедуры и функции аналогичны обычным процедурам и функциям. Примечание: Более подробную информацию об импортировании процедур и функций из библиотек DLL можно найти в Главе 10 "Динамически компонуемые библиотеки". Описания assembler Описания assembler позволяют вам написать всю процедуру или функцию на Ассемблере. Примечание: Более подпробно о процедурах и функциях на Ассемблере рассказывается в Главе 23 "Встроенный Ассемблер". ╒═════════╕ ╒═╕ ┌───────────────┐ ┌────────────┐ блок asm ──┤assembler├─│;├─│раздел описаний├──│оператор asm├─ ╘═════════╛ ╘═╛ └───────────────┘ └────────────┘ Описания inline Директивы inline позволяют записывать вместо блока операторов инструкции в машинном коде. При вызове обычной процедуры компилятор создает код, в котором параметры процедуры помещаются в стек, а затем для вызова процедуры генерируется инструкция CALL. Когда вы вызываете процедуру inline, компилятор генерирует код с помощью директивы inline, а не с помощью инструкции CALL. Таким образом, процедура inline "расширяется" при каждом обращении к ней, аналогично макроинструкции на языке Ассемблера. Приведем два небольших примера процедур типа inline: procedure DisableInterrupts: inline($FA); { CLI } procedure EnableInterrupts; inline($FB); { STI } Примечание: Процедуры типа inline описаны подробно в Главе 22 "Встроенный Ассемблер". Описания функций Описание функции определяет часть программы, в которой вычисляются и возвращается значение. ┌───────────┐ ╒═╕ ┌────────────┐ ╒═╕ описание──│ заголовок ├─│;├──│тело функции│──│;├─────────── функции │ функции │ ╘═╛ └────────────┘ ╘═╛ └───────────┘ ╒══════════╕ ┌───────────────┐ заголовок -│ function ├─│ идентификатор ├─┬─────────────┐ функции ╘══════════╛ └───────────────┘ │  │ ┌────┘ │ │ │ ┌────────────┐ │ │ │ │ список │ │ │ └│ формальных ├─┘ │ │ параметров │ │ └────────────┘ │ ┌───────────────────────────────────────────┘ │ ╒═══╕ ┌────────────────────┐ └─│ : ├────│ тип результата ├────────────── ╘═══╛ └────────────────────┘ ┌────────────────────┐ тип результата ──────┬────│ идентификатор типа ├──────┬─────── │ └────────────────────┘ │ │ ╒════════╕ │ └─────────│ строка ├─────────────┘ ╘════════╛ ┌──────┐ тело функции ────┬───────────────────────────────┬─│ блок ├──── │  │ └──────┘  │ ╒══════╕ ╒═╕ │ │ │ ├──│ near ├───────────│;├───┘ │ │ │ ╘══════╛  ╘═╛ │ │ │ ╒══════╕ │ │ │ ├──│ far ├──────┤ │ │ │ ╘══════╛ │ │ │ │ ╒══════╕ │ │ │ ├──│export├──────┘ │ │ │ ╘══════╛ │ │ │ │ │ │ ┌───────────────────────────┘ │ │ │ │ │ │ ╒═════════╕ ┌──────────┘ │ ├────│ forward ├────────────│ │ │ ╘═════════╛ │ │ │ ╒══════════╕ │ │ ├────│ external ├───────────│ │ │ ╘══════════╛ │ │ │ ┌──────────┐ │ │ └─────│ блок asm ├──────────│ │ └──────────┘ │ │ ┌──────────────────┐ │ └────│ директива inline ├────────┘ └──────────────────┘ В заголовке функции определяется идентификатор функции, формальные параметры (если они имеются) и тип результата функции. Функция активизируется при вызове функции. При вызове функции указывается идентификатор функции и какие-либо параметры, необходимые для вычисления функции. Вызов функции может включаться в выражения в качестве операнда. Когда выражение вычисляется, функция выполняется и значением операнда становится значение, возращаемое функцией. В операторной части блока функции задаются операторы, которые должны выполняться при активизации функции. В модуле должен содержаться по крайней мере один оператор присваивания, в котором идентификатору функции присваивается значение. Результатом функции является последнее присвоенное значение. Если такой оператор присваивания отсутствует или он не был выполнен, то значение, возвращаемое функцией, не определено. Если идентификатор функции используется при вызове функции внутри модуля-функции, то функция выполняется рекурсивно. Приведем далее примеры описаний функции: function Max(a: Vector; n: integer): extended; var x: extended; i: integer; begin x := a(1); for i := 2 to n do if x < a[i] then x := a[i]; Max := x; end; function Power(x: extended; y: integer): extended; var z: extended; i: integer; begin z := 1.0; i := y; while i > 0 do begin if Odd(i) then z := z*x; x := Sqr(x); end; Power := z; end; Аналогично процедурам функции могут описываться, как с ближним типом вызова (near), с дальним типом вызова (far), опережающие (forward), внешние (external), ассемблерные (assembler) или встраиваемые (inline). Однако функции прерываний (interrupt) не допускаются. Описания методов Объявление метода внутри объектного типа соответствует опережающему объявлению (forward) этого метода. Таким образом, метод должен быть реализован где-нибудь после объявления объектного типа и внутри той же самой области действия метода путем определения объявления. Для процедурных и функциональных методов определение описания имеет форму обычного объявления процедуры или функции, за тем исключением, что в этом случае идентификатор процедуры или функции рассматривается как идентификатор метода. Для методов типа конструкторов и деструкторов определение описаний принимает форму описания процедурного метода, за тем исключением, что зарезервированное слово procedure заменяется на зарезервированное слово constructor или destructor. Определение описания метода может повторять (но не обязательно) список формальных параметров заголовка метода в объектном типе. В этом случае заголовок метода должен в точности повторять заголовок в объектном типе в порядке, типах и именах параметров и в типе возвращаемого функцией результата, если метод является функцией. В определяющем описании метода всегда присутствует неявный параметр с идентификатором Self, соответствующий формальному параметру-переменной, обладающему объектным типом. Внутри блока метода Self представляет экземпляр, компонент метода которого был указан для активизации метода. Таким образом, любые изменения значений полей Self отражаются на экземпляре. Область действия идентификатора компонента объектного типа распространяется на блоки процедур, функций, конструкторов и деструктора, которые реализуют методы данного объектного типа. Эффект получается тот же, как если бы в начало блока метода был вставлен оператор with в следующей форме: with Self do begin ... end; Исходя из этих соображений, написание идентификаторов компонентов, формальных параметров метода, Self и любого идентификатора, введенного в исполняемую часть метода, должно быть уникальным. Ниже приводятся несколько примеров реализаций методов: procedure Rect.Intersect(var R: Rect); begin if A.X < R.A.X then A.X := R.A.X; if A.X < R.A.Y then A.Y := R.A.Y; if B.X > R.B.X then B.X := R.B.X; if B.Y < R.B.Y then B.Y := R.B.Y; if (A.X >= B.X) or (A.Y >= B.Y) then Init (0, 0, 0, 0); end; procedure Field.Display; begin GotoXY(X, Y); Write(Name^, ' ', GetStr); end; function NumField.PutStr(S: string): boolean; var E: integer; begin Val(S, Value, E); PutStr := (E = 0) and (Value >= Min) and (Value <= Max); end; Конструкторы и деструкторы Конструкторы и деструкторы являются специализированными формами методов. Используемые в связи с расширенным синтаксисом стандартных процедур New и Dispose, конструкторы и деструкторы обладают способностью размещения и удаления динамических объектов. Кроме того, конструкторы имеют возможность выполнить требуемую инициализацию объектов, содержащих виртуальные методы. Как и все другие методы, конструкторы и деструкторы могут наследоваться, а объекты могут содержать любое число конструкторов и деструкторов. Конструкторы используются для инициализации вновь созданных объектов. Обычно инициализация основывается на значениях, передаваемых конструктору в качестве параметров. Конструктор не может быть виртуальным, так как механизм пересылки виртуального метода зависит от конструктора, который первым совершил инициализацию объекта. Приведем несколько примеров конструкторов: constructor Field.Copy(var F: Field); begin Self := F; end; constructor Field.Init(FX, FY, FLen: integer; FName: string); begin X := FX; Y := FY; GetMem(Name, Length (FName) + 1); Name^ := FName; end; constructor StrField.Init(FX, FY, FLen: integer; FNAme: string); begin Field.Init(FX, FY, FLen, FName); GetMem(Value, Len); Value^ := ''; end; Главным действием конструктора порожденного (дочернего) типа, такого как указанный выше StrField.Init, почти всегда является вызов соответствующего конструктора его непосредственного родителя для инициализации наследуемых полей объекта. После выполнения этой процедуры, конструктор инициализирует поля объекта, которые принадлежат только порожденному типу. Деструкторы (сборщики мусора) являются противоположностями конструкторов и используются для очистки объектов после их использования. Обычно очистка состоит из удаления всех полей-указателей в объекте. Примечание: Деструктор может быть виртуальным и часто является таковым. Деструктор редко имеет параметры. Приведем несколько примеров деструкторов: destructor Field.Done; begin FreeMem(Name, Length (Name^) + 1); end; destructor StrField.Done; begin FreeMem(Value, Len); Field.Done; end; Деструктор производного типа, такой как указанный выше StrField.Done, обычно сначала удаляет введенные в порожденном типе поля указателей, а затем в качестве последнего действия вызывает соответствующий деструктор непосредственного родителя для удаления наследованных полей указателей объекта. Параметры В описании процедуры или функции задается список формальных параметров. Каждый параметр, описанный в списке формальных параметров, является локальным по отношению к описываемой процедуре или функции и в модуле, связанным с данной процедурой или функцией на него можно ссылаться по его идентификатору. ╒═══╕ ┌─────────────────────┐ ╒═══╕ список ────│ ( ├──│ описание параметров │─┬│ ) ├────── формальных ╘═══╛  └─────────────────────┘ │ ╘═══╛ параметров │ ╒═══╕ │ └─────────┤ ; │──────────┘ ╘═══╛ ┌────────────────────────┐ описание ───┬──────────│ список идентификаторов ├─┬───────── параметров │  └────────────────────────┘ │  │ ╒═════╕ │ ┌─────────────────────┘ │ └│ var ├─┘ │ ╒═══╕ ┌───────────────┐ │ ╘═════╛ └│ : ├─│ тип параметра ├─┘ ╘═══╛ └───────────────┘ ┌────────────────────┐ тип параметра ────┬───────┤ идентификатор типа ├────────────── │ └────────────────────┘  │ ╒════════╕ │ ├───────────│ string ├────────────┤ │ ╘════════╛ │ │ ╒════════╕ │ └───────────│ file ├────────────┘ ╘════════╛ Существует три типа параметров: значение, переменная и нетипизованная переменная. Они характеризуются следующим: 1. Группа параметров, перед которыми отсутствует ключевое слово var и за которыми следует тип, является списком параметров-значений. 2. Группа параметров, перед которыми следует ключевое слово var и за которыми следует тип, является списком параметров-переменных. 3. Группа параметров, перед которыми стоит ключевое слово var и за которыми не следует тип, является списком нетипизованных параметров-переменных. Параметры-значения Формальный параметр-значение обрабатывается, как локальная по отношению к процедуре или функции переменная, за исключением того, что он получает свое начальное значение из соответствующего фактического параметра при активизации процедуры или функции. Изменения, которые претерпевает формальный параметр-значение, не влияют на значение фактического параметра. Соответствующее фактическое значение параметра-значения должно быть выражением и его значение не должно иметь файловый тип или какой-либо структурный тип, содержащий в себе файловый тип. Фактический параметр должен иметь тип, совместимый по присваиванию с типом формального параметра-значения. Если параметр имеет строковый тип, то формальный параметр будет иметь атрибут размера, равный 255. Параметры-переменные Параметр-переменная используется, когда значение должно передаваться из процедуры или функции вызывающей программе. Соответствующий фактический параметр в операторе вызова процедуры или функции должен быть ссылкой на переменную. При активизации процедуры или функции формальный параметр-переменная замещается фактической переменной, любые изменения в значении формального параметра-переменной отражаются на фактическом параметре. Внутри процедуры или функции любая ссылка на формальный параметр-переменную приводит к доступу к самому фактическому параметру. Тип фактического параметра должен совпадать с типом формального параметра-переменной (вы можете обойти это ограничение с помощью нетипизованного параметра-переменной). Если формальный параметр имеет строковый тип, ему присваивается атрибут длины, равный 255, и фактический параметр должен также иметь строковый тип и атрибут длины, равный 255. Файловый тип может передаваться только, как параметр-переменная. При ссылке на фактический параметр-переменную, связанную с индексированием массива или получением указателя на объект, эти действия выполняются перед активизацией процедуры или функции. Объекты Правила совместимости объектных типов по присваиванию также применимы к параметрам-переменным объектного типа: для формального параметра типа T1 фактический параметр должен быть типа T2, если тип T2 является наследником типа T1. Например, методу Field.Copy может передаваться экземпляр типа Field, NumField, ZipField или любого другого типа, являющегося производным по отношению к типу Field. Нетипизованные параметры-переменные Когда формальный параметр является нетипизованным параметром-переменной, то соответствующий фактический параметр может представлять собой любую ссылку на переменную, независимо от ее типа. В процедуре или функции у нетипизованного параметра-переменной тип отсутствует, то есть он несовместим с переменными всех типов, пока ему не будет присвоен определенный тип с помощью присваивания типа переменной. Приведем пример нетипизованных параметров-переменных: function Equal(var source,dest; size: word): boolean; type Bytes = array[0..MaxInt] of byte; var N: integer; begin N := 0; while (N Bytes(source)[N] do Inc(N); Equal := N = size; end; Эта функция может использоваться для сравнения любых двух переменных любого размера. Например, с помощью описаний: type Vector = array[1..10] of integer; Point = record x,y: integer; end; var Vec1, Vec2: Vector; N: integer; P: Point; и вызовов функций: Equal(Vec1,Vec2,SizeOf(Vector)) Equal(Vec1,Vec2,SizeOf(integer)*N) Equal(Vec[1],Vec1[6],SizeOf(integer)*5) Equal(Vec1[1],P,4) сравнивается Vес1 с Vес2, сравниваются первые N элементов Vес1 с первыми N элементами Vес2, сравниваются первые 5 элементов Vес1 с последними пятью элементами Vес2 и сравниваются Vес1[1] с Р.х и Vес2[2] с P.Y. Процедурные типы Являясь расширением стандартного Паскаля, Турбо Паскаль позволяет интерпретировать процедуры и функции, как объекты, которые можно присваивать переменным и передавать в качестве параметров. Таким образом, допускается использование процедурных типов. Примечание: Процедурные типы определяются также в Главе 3 ("Типы"). Процедурные переменные После определения процедурного типа появляется возможность описывать переменные этого типа. Такие переменные нызывают процедурными переменными. Например, с учетом описаний типа из предыдущего примера, можно объявить следующие переменные: 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 байта (два слова), в которых содержится адрес памяти. В первом слове хранится смещение, во втором - сегмент. Параметры процедурного типа Поскольку процедурные типы допускается использовать в любом контексте, то можно описывать процедуры или функции, которые воспринимают процедуры и функции в качестве параметров. В следующем примере показывается использование параметров процедурного типа для вывода трех таблиц различных арифметических функций: program Tables; type Func = function(X,Y: integer): integer; function Add(X,Y: integer): integer; far; begin Add := X + Y; end; function Multiply(X,Y: integer): integer; far; begin Multiply := X*Y; end; function Funny(X,Y: integer): integer; far; begin Funny := (X+Y) * (X-Y); end; procedure PrintTable(W,H: integer; Operation: Func); var X,Y : integer; begin for Y := 1 to H do begin for X := 1 to W do Write(Operation(X,Y):5); Writeln; end; Writeln; end; begin PrintTable(10,10,Add); PrintTable(10,10,Multiply); PrintTable(10,10,Funny); end. При работе программа Table выводит три таблицы. Вторая из них выглядит следующим образом: 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100 Параметры процедурного типа особенно полезны в том случае, когда над множеством процедур или функций нужно выполнить какие-то общие действия. В данном случае процедуры PrintTable представляет собой общее действие, выполняемое над функциями Add, Multiply и Funny. Если процедура или функция должны передаваться в качестве параметра, они должны удовлетворять тем же правилам совместимости типа, что и при присваивании. То есть, такие процедуры или функции должны компилироваться с директивой far, они не могут быть встроенными функциями, не могут быть вложенными и не могут описываться с атрибутами inline или interrupt. ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄АRП  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄АЮk`~  й  л  ?  y  ╗   <7<ЁЁ╗ї      @  В  ┐  №  9  v  │  Ё │ю  )  X  С  ┼  ∙  -  V  X  П  Ё П═    A  {  ╡  я  )   c   Э   ╫   Ё ╫    K   Е   ┐   ∙   3   m   з   с      Ё  U   П   ╔      =   w   з   й   #  Ф  Ё Ф>  h  j  а  к  ╛  ╩  ▀  Ё     Ё  ,  E  Z  ~  Й  Л  ╖  ╣  G  н  Ё н5  ╘  ╗  т  ф  ▓    p  Ф  Ц  Ё Цу  %  @  ^  Е  и  ┘  █      Ё ▓    ъ  )   F   W   Y    !  5!  7!  Ё 7!╨#  q$  и$  к$  ┌$  ¤$   %  %  %  $%  Ё $%/%  G%  S%  \%  e%  |%  Е%  О%  Щ%  Ы%  Ё Ы%|&  ─&  я&  ё&  я'  ^(  Ъ(  Ь(  ╫(  щ(  Ё щ(ы(  &)  8)  :)  |)  О)  Р)  ╥)  ф)  ц)  Ё ц)√)  ¤)  +  8+  h+  j+  Z,  ─,  e-  Р-  Ё Р-Т-  ь-  g.  й.  э.  //  1/  [/  ]/  Й1  Ё Й1┬1  √1  ¤1  Z2  Д2  Ж2  щ2   3  c3  Ъ3  Ё Ъ3╡3  у3  !4  _4  Э4  █4  5  W5  Х5  ╙5  Ё ╙56  E6  И6  ╝6  ╛6  Є6  57  p7  л7  ц7  Ё ц78  8  T8  Ш8  ┌8  9  ^9  а9  т9  $:  Ё $:f:  и:  ъ:  ,;  n;  ░;  Є;  4<  k<  в<  Ё в<┘<  =  G=  ~=  ╡=  ь=  #>  Z>  И>  К>  Ё К> ?  _@  B  ВB  ▒B  │B  шB  ЄB  C  C  Ё C%C  8C  oC  БC  МC  ОC  ╟C  ╤C  цC  ·C  Ё ·CD   D  7D  CD  dD  yD  ДD  ЦD  бD  гD  Ё гD▒E  █E  ▌E  яF  ▀G  J  ЕK  нL  └L  ╠L  Ё ╠L╫L  тL  фL  йM  цM  шM  N  !N  IN  qN  Ё qNЩN  ┴N   N   O   O  +O  7O  MO  pO  {O  Ё {O}O  ▒O  ╗O  ╨O  ▄O  ЎO  7P  BP  DP  sP  Ё sPuP  yR  ┼S  ЎS  °S  $T  0T  CT  NT  PT  Ё PTФT  аT  ▒T  ┬T  ьT  U  U  U  OU  xU  Ё xUДU  нU  ╔U  ▀U  ъU  ьU  XW  )X  ЪX  ╩X  Ё ╩X╠X  ъX  ўX  #Y  /Y  1Y  RY  _Y  }Y  ТY  Ё ТYЮY  аY  ═Z  ЇZ  ЎZ  *\  e\  з\  т\  ]  Ё ]L]  u]  w]  н]  я]  ,^  i^  ж^  у^  _  Ё _ _  S_  Х_  ╬_  `  @`  y`  ▓`  ы`  a  Ё aa  Сa  b  еb  ?c  jc  lc  ┌d  Ьe  qf  Ё qfЭf  Яf  Th  3j  {j  



Похожие:

Pas-pg.dos/Tpw8 iconДокументы
1. /Tb_c_ug.dos/1cont.txt
2. /Tb_c_ug.dos/1intr.txt
Pas-pg.dos/Tpw8 iconДокументы
1. /Td.dos/1Cont.txt
2. /Td.dos/1Glossary.txt
Pas-pg.dos/Tpw8 iconДокументы
1. /Tp6progg.dos/Pg00.txt
2. /Tp6progg.dos/Pg01.txt
Pas-pg.dos/Tpw8 iconДокументы
1. /CИСТЕМА ПРОГРАММИРОВАНИЯ НА МАКРОАССЕМБЛЕРЕ MS-DOS/A1P0.TXT
2. /CИСТЕМА...

Pas-pg.dos/Tpw8 iconДокументы
1. /Tvision.dos/Tv00.txt
2. /Tvision.dos/Tv01.txt
Pas-pg.dos/Tpw8 iconДокументы
1. /Info.txt
2. /Операционная система MS DOS....

Pas-pg.dos/Tpw8 iconДокументы
1. /Et situ'n existais pas/Et situ'n existais pas.pdf
Pas-pg.dos/Tpw8 iconДокументы
1. /Et situ'n existais pas/Et situ'n existais pas.pdf
Pas-pg.dos/Tpw8 iconДокументы
1. /Turbo_c.dos/St00.txt
2. /Turbo_c.dos/St01.txt
Pas-pg.dos/Tpw8 iconДокументы
1. /Tp6userg.dos/Ug00.txt
2. /Tp6userg.dos/Ug01.txt
Разместите кнопку на своём сайте:
Документы


База данных защищена авторским правом ©podelise.ru 2000-2014
При копировании материала обязательно указание активной ссылки открытой для индексации.
обратиться к администрации
Документы

Разработка сайта — Веб студия Адаманов