Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Процедуры, играющие роль операторов

Поиск

С развитием языка Паскаль в рамках среды Delphi 7 в него добавлялось множество

новых полезных возможностей, нередко заимствованных из других языков про-

граммирования. Эти возможности вводились в Паскаль не в виде новых операторов,

что нарушило бы идеологию языка, а в виде стандартных подпрограмм, которые,

хотя и не выделяются цветом наравне с другими ключевыми словами, тем не менее,

фактически являются таковыми. И реализуются подобные подпрограммы не в виде

обращений к машинному коду, хранимому в программной библиотеке. Компиля-

тор не добавляет в генерируемый код ссылку, а превращает данную ≪процедуру≫,

подобно обычным операторам, в небольшой набор машинных инструкций (а иногда

и в одну такую инструкцию).

Одна из таких весьма полезных процедур — Exit (без параметров).

Exit;

При ее выполнении происходит немедленное завершение текущей подпрограммы

и передача управления вызывающей программе. Такая возможность часто требу-

ется, когда логика, реализуемая в подпрограмме, достаточно сложна и организовать

линейный выход из подпрограммы (по достижении ее конца) затруднительно.

Подпрограммы 65

Полезна подпрограмма Exit и в тех случаях, когда при определенных значениях

параметров вычислить значение функции удается сразу. Например, если при вычис-

лении факториала числа параметр равен 1, можно сразу определить возвращаемое

значение, также равное 1, и покинуть подпрограмму.

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

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

основании таких типов, обладающих равными правами с другими типами, можно

описывать переменные, что позволяет передавать подпрограммы в качестве пара-

метров. Подобный прием в некоторых случаях помогает эффективно решить слож-

ную задачу, с трудом поддающуюся кодированию обычным способом, однако

пользоваться им нежелательно, по крайней мере начинающим разработчикам.

Примеры:

type TSumFun = function! А, В: Integer): integer;

TEmptyProc = procedure;

TMyProc = procedure (X: Real);

var SumP: TSumFun;

EmptyProc: TEmptyProc;

MyPr: TMyPrOC;

ВНИМАНИЕ При описании процедурных типов названия подпрограмм не указы-

ваются. Приводится только основная схема заголовка.

Далее, если в тексте описана подпрограмма, то ее можно присвоить переменной

соответствующего типа:

SumP:= Sum;

EmptyProc:= Demo;

ВНИМАНИЕ В правой части оператора присваивания указывается только назва-

ние подпрограммы без параметров.

Для обращения к нужной подпрограмме теперь можно указывать не только ее имя,

но и имя переменной, хранящей ≪описание≫ этой подпрограммы:

X: = SumP (2,2),-

Реально здесь произойдет вызов функции Sum с аргументами 2 и 2.

ЗАМЕЧАНИЕ Переменные процедурных типов являются указателями. В них хра-

нится только адрес ячейки оперативной памяти, где начинается со-

ответствующая процедура.

Подпрограмму можно передавать в другую подпрограмму как параметр. Это удобно,

когда над аргументами надо выполнять различные сложные действия в зависимости

3 За* 348

66 Урок 1. Язык Delphi (Object Pascal] и его использование

от некоторых условий. В приведенном ниже примере функция MathAction будет

вычислять или сумму, или разность параметров, в зависимости от того, какая функ-

ция указана в качестве параметра.

type TMathFun = function! X,Y: Integer): Integer;

function Add(X,Y: Integer): Integer;

Begin

Add:= X+Y

end;

function Sub(X,Y: Integer): Integer;

Begin

Sub:= X-Y

end;

function MathActionl X,Y: Integer;

Proc: TMathFun): Integer;

begin

Result:= Proc! X,Y)

end;

Теперь к функции MathAction можно обращаться так:

WriteLn(MathActioni 10, 4, Add));

при этом будет напечатано число 14, или так:

WriteLnl MathActionl 10, 4, Sub) };

В этом случае будет напечатано число 6.

Чтобы проверить, содержит ли переменная процедурного типа описание конкретной

подпрограммы, используется стандартная функция AssignedQ, которая в качестве

аргумента получает процедурную переменную, а возвращает значение типа Boolean

(если оно равно True, то переменная имеет корректное значение).

С переменными, хранящими указатели на функции, надо обращаться осторожно.

Переменной, хранящей указатель на процедуру, можно присвоить значение такой же

переменной. В то же время, если в левой части оператора присваивания стоит пере-

менная типа, совпадающего с типом значения, возвращаемого функцией, то про-

изойдет вызов функции. Когда надо выполнять копирование указателей, а когда —

вызывать функции, решает компилятор в зависимости от контекста.

type TP = procedure;

TF = function: integer,-

var pi, p2: TP;

fl, £2: TF;

N: Integer;

Операторы 67

procedure А;

begin

end;

function В: integer;

begin

В:= О

end;

p2:= A;

Pi:= p2;

// произойдет копирование указателя

f2: = В,-

fl:- f2;

// произойдет копирование указателя

N:= f2;

// произойдет вызов функции В

//и запись значения в переменную N

Указатели на подпрограммы

Хотя переменные, описанные как процедурные типы, фактически являются указате-

лями, от программиста эта их особенность скрыта. Но Паскаль разрешает также

явно описывать переменные-указатели на подпрограммы. Для этого в языке введен

особый тип данных Pointer, представляющий собой указатель на информацию, не

имеющую конкретного типа. Получение адреса начала подпрограммы выполняется

с помощью операции @, так же, как и для получения адреса любых других данных.

var X: Pointer;

X:= OMyProcedure;

Подобным способом в программе определяются и процедурные константы-указа-

тели:

const P: Pointer = OMyFunction;__

(объявление ссылок на метки??)

@F адрес того,что лежит в переменной

@@Fадрес самой переменной

 

 



Поделиться:


Последнее изменение этой страницы: 2017-02-21; просмотров: 205; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.227.73 (0.006 с.)