Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Проблема совместимости




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

Аналогичным образом должны совпадать типы возвращаемых значений в случае функций.

Механизм процедурных типов предоставляет программисту весьма широкие и удобные возможности при разработке программ. Корректная работа требует соблюдения следующих правил.

- Подпрограмма, присваиваемая процедурной переменной, должна быть оттранслирована в режиме «дальнего типа вызовов». Для достижения эффекта необходимо перед подпрограммой или группой подпрограмм расположить директиву компилятора $F со знаком +, а в конце группы со знаком -.

Пример

{$F+}

function Add (a,b: real):real;

begin

Add:=a+b

end;

function Sub (a,b: real):real;

begin

Sub:=a-b

end;

{$F-}

Если необходимо распространить действие этой директивы на всю программу, то достаточно одну {$F+} поместить в самом начале текста.

Эквивалентом директивы компилятора {$F+} является служебное слово far, которое должно быть записано перед блоком подпрограммы. (другой - «близкий» тип вызова задаётся служебным словом near).

function add (a,b: real):real; far;

begin

Add:=a+b

end;

- Подпрограмма, присваиваемая процедурной переменной, не должна быть стандартной процедурой или функцией. Это ограничение при необходимости можно легко обойти, заключив вызов стандартной подпрограммы в «оболочку», после чего её можно использовать в качестве присваивания.

Пример

Var

Func: function (s: string): byte;

….......

function Mylength (s: string): byte; far;

begin

Mylength:=length(s)

end;

………

Func:= Mylength;

- Важное ограничение – обсуждаемые подпрограммы не могут быть вложенными в другие подпрограммы.

- Подпрограммы, присваиваемые процедурным переменным, не могут быть подпрограммами специального вида, содержащими спецификации interrupt и конструкцию inline.

Можно описывать процедуры и функции, параметрами которых являются процедурные переменные.

Можно организовать подпрограмму, которая будет выполнять некоторые общие действия для различных подпрограмм – параметров.

Пример

program Tables;

type

func= function(x, y: integer): integer;

function Add(a, b: integer):integer; far;

begin

Add:=a+b;

end;

function Mult(a, b: integer): integer; far;

begin

Mult:=a+b;

end;

procedure MakeTable(w, h:integer; operation: func);

var

i, j:integer;

begin

write(‘ ‘);

for i:=1 to w do write(‘_ _ _ _ _ ‘);

writeln;

for i:=1 to h do begin

write(i: 5,’ | ‘);

for j:=1 to w do

write(operation(j, i): 5);

writeln;

end;

writeln; end;

begin

Make_table(10,10, Add);

Make_table(10,10, Mult);

end.

Два вызова процедуры MakeTable, которая строит таблицы, используя для вычисления в первом случае функцию Add, во втором – Mult.

Переменные процедурных типов можно передавать в качестве параметров подпрограммы.

Функции, возвращающие значения процедурных типов, не допускаются.

В общем случае использование процедурной переменной в операторе или выражении означает вызов присвоенной данной переменной процедуры или функции.

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

Пример

type

IntFunc= function: integer;

var

f: IntFunc;

n: integer;

function ReadInt: integer; far;

var

i: integer;

begin

read(i);

ReadInt:=i;

end;

begin

f:= ReadInt; {присваивание значения процедуры}

n:= Readint; { присваивание результата функции}

end.

Первый оператор в основной программе присваивает значение процедуры Readint (её адрес) процедурной переменной F, второй вызывает функцию Readint и присваивает полученное значение переменной n. Полученные значения процедуры или вызов функции различаются по типу присваиваемой переменной(f или n).

Дополнение Директивы подпрограмм дают информацию о размещении подпрограмм.

1. FORWARD- директива заголовка подпрограммы описанной дальше по тексту.

2. FAR, NEAR- директивы формирования «дальнего» адреса и «ближнего» адреса.

3. EXTERNAL- директива внешней подпрограммы.

4. ASSEMBLER- директива подпрограммы, написанной на ассемблере.

5. INLINE- директива, позволяющая включить в программу часть, написанную на ассемблере.

6. INTERRUPT – директива процедуры обработки прерываний.

(См. пункт 10.5.

Епанишников А.М., Епанешников В.А. Программирование в среде Turbo -Pascal 7.0. М.: Диалог- МИФИ. 2001. -288 с.)

 

Рекурсия

В теле подпрограммы известны (доступны) все объекты, описанные в блоке, в том числе и имя самой подпрограммы. Таким образом, внутри тела подпрограммы возможен вызов самой подпрограммы. Процедуры и функции, использующие вызовы “самих себя”, называются рекурсивными. Допустима косвенная рекурсия, при которой, например, процедура А вызывает процедуру В,а та, в свою очередь, вызывает процедуру С, которая вызывает первоначальную процедуру А.

Пример Вычисление факториала

 

0!=1; 1!=1; n!=1*2*3… (n-1)*n n!=(n-1)!*n.

function Fact (n: word): longint;

begin

if n=1 then

Fact:=1

else

Fact:=n*Fact(n-1)

end;

В языке Pascal нет никаких ограничений на рекурсивные вызовы подпрограмм. Необходимо только хорошо понимать, что каждый очередной рекурсивный вызов приводит к образованию новой копии локальных объектов подпрограммы. Все эти копии, соответствующие цепочке активизированных и незавершённых рекурсивных вызовов, существуют независимо друг от друга.

 

Побочный эффект

Пример

program SideEffect;

var

a, z: integer;

function change(x: integer):integer;

begin

z:=z-x;

change: =sqr(x)

end;

begin

z:=10; a:=change(z);

writeln(a, z);

z:=10; a:=change(10)*change(z) {вызывается первым!!} writeln(a, z);

z:=10; a:=change(z)*change(10);

wrireln(a,z);

end.

Результат выполнения программы program SideEffect.

Вывод на экран

100 0

10000 -10

0 0

Анализ возможных вариантов работы программы представлен в таблице. Результат сравнения результатов анализа и результата работы программы program SideEffect показывают, что первым осуществляется вызов change(z), а затем change(10).

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

 

значения после a z
1 вызова    
вывод на экран    
возможный вариант первым вызывается change(10)
2 вызова    
3 вызова    
вывод на экран    
  первым вызывается change(z)
2 вызова    
3 вызова   -10
вывод на экран   -10
     
возможный вариант первым вызывается change(10)
4 вызова    
5 вызова    
вывод на экран    
  первым вызывается change(z)
4 вызова    
5 вызова   -10
вывод на экран   -10

 

Поделиться:





Читайте также:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...