На этом шаге мы рассмотрим правила использования процедурных типов.
Процедурные типы позволяют объявлять переменные, которым допускается присваивание имен процедур, функций и методов, а также передавать такие переменные и имена в качестве параметров.
Описание процедурных типов имеет практически такой же синтаксис, как и объявление процедур, функций и методов. Отличительной особенностью процедурных типов является отсутствие идентификатора процедуры/функции, поскольку для типа конкретное имя процедуры не имеет значения.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; Edit1: TEdit; Edit2: TEdit; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; {Указательный тип на функцию.} TMyFunc = function (X : Integer):Real; var Form1: TForm1; implementation {$R *.dfm} {Первая функция.} function FirstFunc ( X : Integer ): Real; begin FirstFunc := SQR ( X ) /2; end; {Вторая функция.} function SecondFunc ( X : Integer ): Real; begin SecondFunc := SQRT ( X )*2; end; procedure TForm1.FormCreate(Sender: TObject); var MyFunc:TMyFunc; {Указатель на функцию.} Res : Real; St : String; begin MyFunc := FirstFunc; {Присвоили адрес первой функции.} Res := MyFunc(16) ; { Res = 128 } Str (Res:7:2, St); Edit1.Text:= St; MyFunc := SecondFunc; {Присвоили адрес второй функции.} Res := MyFunc (16) ; { Res = 8 } Str (Res:7:2, St); Edit2.Text:= St; end; end.
Текст этого примера можно взять здесь.
Результат работы приложения представлен на рисунке 1:
Рис.1. Результат работы приложения
Переменная процедурного типа представляет собой адрес памяти, где размещается процедура и, таким образом, фактически является указательной переменной особого вида.
В Object Pascal процедурные типы можно разделить на две категории:
Указатели на глобальные процедуры описываются, как рассмотрено выше, а при объявлении указателей на методы в описании процедурного типа после списка формальных параметров ставятся ключевые слова of object. При этом директива дальнего вызова {$F+} не требуется:
type TMyMethod = procedure ( Sender : Object ) of object;
В остальных аспектах работа с указателями на глобальные процедуры и на методы одинакова.
В объявлении процедурных типов может быть еще указана одна из стандартных директив register, cdecl, pascal, stdcall, которые определяют способ соглашения о передаче параметров при вызове. По умолчанию действует директива register (при включенной директиве оптимизации {$O+}) или директива pascal (при выключенной оптимизации {$O-}).
Назначение перечисленных директив описано в таблице 1:
Директива | Описание |
---|---|
register | Определяет следующие характеристики передачи параметров:
|
pascal | Определяет следующие характеристики передачи параметров:
|
cdecl | Определяет следующие характеристики передачи параметров:
|
stdcall | Определяет следующие характеристики передачи параметров:
|
Приведем еще несколько примеров описания процедурных типов:
type TProc1 = procedure (X, Y : Real); TFuncl = function (X: Integer): Real; TProc2 = procedure (A :MyType); pascal; TFunc2 = function (I,J: Byte; X,Y: Char): String; register; ТРrос3 = procedure (Sender : Tobject) of object; cdecl;
При описании процедур, функций и процедурных типов могут также использоваться стандартные директивы assembler, forward, external, назначение которых осталось таким же, как и в предыдущих реализациях Borland (Turbo) Pascal.
На следующем шаге мы рассмотрим строковые типы.