Шаг 32.
Пользовательские типы. Процедурные типы

    На этом шаге мы рассмотрим правила использования процедурных типов.

    Процедурные типы позволяют объявлять переменные, которым допускается присваивание имен процедур, функций и методов, а также передавать такие переменные и имена в качестве параметров.

    Описание процедурных типов имеет практически такой же синтаксис, как и объявление процедур, функций и методов. Отличительной особенностью процедурных типов является отсутствие идентификатора процедуры/функции, поскольку для типа конкретное имя процедуры не имеет значения.


    Пример. С помощью указателя на функцию вычислить значения первой и второй функции.
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:

Таблица 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.

    На следующем шаге мы рассмотрим строковые типы.




Предыдущий шаг Содержание Следующий шаг