Второй способ передачи параметров в процедуру или функцию — "по значению", если перед формальным параметром не стоит зарезервированное слово var. В этом случае в программе в качестве фактического параметра можно писать произвольное выражение соответствующего типа (совместимого по присваиванию). Для формального параметра при вызове процедуры создается временная переменная данного типа. Ей присваивается значение выражения, вычисляемое в процессе присваивания (вот почему говорят о передаче параметра "по значению"). Затем с этой переменной выполняются все действия, описанные в процедуре для формального параметра. Перед завершением процедуры временная переменная (ее называют локальной) автоматически уничтожается, поэтому с ее помощью ничего нельзя передать "наружу". Другими словами — это передача параметра типа in. В некоторых других языках программирования (например, ADA), возможна передача параметра типа out. При этом в процедуре такой параметр может стоять только в левой части присваивания, и его нельзя использовать в выражениях в правой части присваивания или в фактических параметрах процедур.

Передача параметра через указатель – это явная передача адреса ячейки. Единственное отличие от передачи по ссылке заключается в том, что для доступа к ячейке внутри подпрограммы требуется ставить символ ^ после имени указателя.

2.13. Локальные и глобальные переменные. Побочный эффект функции. Вложенность процедур и функций. Правила видимости.

В приведенных выше примерах часть переменных описана в блоке описания переменных программы. Такие переменные называются глобальными. Они существуют в любой момент выполнения программы. Другая часть переменных описана внутри процедуры или функции. Это — локальные переменные. В отличие от глобальных они создаются не в момент запуска программы, а в момент каждого очередного вызова процедуры, и после окончания работы процедуры уничтожаются. (Для повышения эффективности работы часть процедур и локальных переменных не уничтожается полностью, а хранится в стеке. Это дает возможность быстро вызывать их. Однако с точки зрения программиста это совершенно не меняет ситуации с их "существованием" и правилами видимости). Поэтому эти переменные и называются локальными: они существуют только внутри соответствующей процедуры. "Снаружи" процедуры локальные переменные этой процедуры не имеют смысла, и попытка вызова такой переменной приведет к сообщению компилятором об ошибке. Говорят, что локальная переменная невидима вне своей процедуры. С другой стороны, глобальные переменные видимы в любом месте программы т. е. их можно вызывать и внутри процедур и функций. Поэтому их называют глобальными переменными. Глобальные переменные иногда используются для передачи данных внутрь процедуры не через список параметров в заголовке процедуры, а "напрямую". Как правило этот путь нельзя считать хорошим, т. к. обычно он не соответствует принципам структурного программирования. С другой стороны, в ряде случаев бывает целесообразно менять значение некоторых нелокальных переменных в процессе работы процедуры, т. е. получать так называемый побочный эффект работы процедуры. Этот способ часто используется в объектном программировании для приведения в соответствие значений нескольких взаимно зависимых параметров.

НЕ нашли? Не то? Что вы ищете?

2.14. Пример на правила видимости и передачи параметров

unit factorials;

uses. . . ;

var

k, n,m: integer; {глобальные целые переменные}

p:extended;

ch: char; {глобальная литерная переменная}

function fact1(n:integer): extended;{процедура-функция, передача

входного параметра n по значению}

var i: integer;

begin

if n=0 then n:=1;

result:=1;

for i:=1 to n do result:=result*i;

end;

procedure fact2;{процедура, передача входного параметра через

глобальную переменную n, возврат результата через

глобальную переменную p}

var i: integer;

result:extended;

begin

if n=0 then n:=1;

result:=1;

for i:=1 to n do result:=result*i;

p:=result;

end;

procedure fact3(n:integer; var r:extended);{процедура, передача

входного параметра n по значению,

возврат результата через параметр r по имени}

var i: integer;

result:extended;

begin

if n=0 then n:=1;

result:=1;

for i:=1 to n do result:=result*i;

r:=result;

end;

function fact4(n:integer):extended; {процедура-функция, передача

входного параметра n по значению, побочный

эффект – изменение глобальной переменной m}

var

i: integer;

begin

if n=0 then n:=1;

result:=1;

for i:=1 to n do result:=result*i;

fact4 =result;

m:=m+1;{побочный эффект}

end;

begin {тело основной программы}

k:=…;

m:= 0;n:=…;p=…;

case ch of

'1' : p := fact1( n );

'2' : fact2 ;

'3' : fact3( n , p );

'4' : p := fact4( n );

end;

……

End.

2.15. Рекурсия

Очень часто в математических выражениях используется так называемое рекурсивное определение функций:

factorial(1)=1; для n>1: factorial(n)= factorial(n-1)*n.


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

function factorial(n:integer):extended;

begin

result:=1;

if n>=1 then result:=n*factorial(n-1)

end;

У рекурсии есть недостатки: а) при каждом вложенном вызове создается копия локальных переменных процедуры, они храняться в стеке. При большой глубине вложенности стек может переполниться; b) очень часто встречается ситуация бесконечной рекурсии. Так, если бы мы не написали условия n>=1, рекурсные вызовы продолжались бы вплоть до переполнения:

function factsfoo(n:integer):extended;

begin

result:>=n*factorial(n-1)

end;

Основные принципы объектно-ориентированного программирования (ООП) на примере языка Object Pascal (Delphi) со статической версией объектной модели

Рассматриваемая версия объектной модели характерна для языка TurboPASCAL (TP5.5 – TP7.0) и очень близка к объектной модели C++ ( за исключением того, что в C++ поддерживается также множественное наследование и ряд других дополнительных возможностей). В Delphi эта модель поддерживается, но рассматривается как устаревшая. Основной считается модель с динамически создаваемыми объектами, во многом близкая по идеологии к объекной модели языка Java.

2.1. Инкапсуляция. Объект. Поля данных и методы объекта

Инкапсуляцией называется объединение каких-либо относительно независимых элементов в единое целое. В стандартном PASCAL существует тип record — "Запись":

type

tLocation=

record {поля записи}

X, Y:Integer

end;

var Location1,Location2:tLocation;

a:integer;

Поля записи — самостоятельные переменные. Доступ к ним — через квалификацию с помощью точки (составное имя с разделительной точкой). К полям можно обращаться по отдельности. Например, присвоить переменной a значение поля X:

a:=Location1.X

Либо изменить значение поля Y:

Location1.Y:=212

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

Location2:=Location1

при этом полю X записи Location1 будет присвоено значение X записи Location2, и, аналогично, полю Y в Location1 — значение Y записи Location2.

Развитием идеи объединения (инкапсуляции) различных полей стали объекты.

Пример:

объект:

точка на экране tDot;

ее данные:

координаты X и Y — целые переменные;

светится или нет на экране active — булевская переменная;

ее методы действия:

"нарисовать": Show;

"скрыть": Hide;

"передвинуть по X и Y на величины dX и dY": Move(dX, dY)

"передвинуть в точку с координатами X и Y": MoveTo(X, Y)

Использование в программе:

var aDot:tDot;

...

aDot. X:=10; {координате X точки Dot присвоить значение 10}

aDot. Y:=20;

aDot. Show; {вызвать метод показа точки Show; говорят: "точка себя рисует"}

Описание методов:

procedure tDot. Show;

begin

… {рисование точки текущим цветом пера}

active:=true;

end;

procedure tDot. Hide;

begin

… {рисование точки цветом фона}

active:=false;

end;

procedure tDot. Move(dX, dY:Integer);

begin

Hide;

X:=X+dX;

Y:=Y+dY;

Show;

end;

3.2 Задание модуль класса (статическая объектная модель)

Теперь мы можем наметить, как будет выглядеть модуль с нашим классом:

Unit myFigure;

uses …;

interface

type

tDot=

object

X, Y:Integer;

active:Boolean;

procedure Show;

procedure Hide;

procedure MoveBy(dX, dY:Integer); {сдвиг на dX, dY}

procedure MoveTo(NewX, NewY:integer);{рисование в точке NewX, NewY}

end;

tCircle=

object(tDot)

...

end;

implemetation

{——— раздел реализации ———}

procedure tDot. Show;

begin

...

end;

procedure tDot. Hide;

begin

...

end;

procedure tDot. MoveBy(dX, dY:Integer);

begin

...

end;

procedure tDot. moveTo(X,_,Y_:integer);

begin

end;

begin

{раздел инициации. Всегда делать пустым!!!}

end.

Модули. Секции декларации, интерфейса и реализации. Области видимости.

На самом деле общая структура модуля при наличии в нем класса несколько сложнее. Обсудим ее более подробно.

Написание собственного модуля (unit) начинается с указания имени модуля. В нашем случае он называется myFigure. Он должен храниться в файле с тем же именем, но с расширением. pas (файл языка PASCAL), т. е. myFigure. pas.

unit myFigure;

секция декларации

interface

uses... , m1,…; {наш модуль кроме списка модулей, автоматически созданного Delphi, использует модули m1 и т. Д.}

type

tDot=

object

active:Boolean;

X, Y:integer;

procedure Show;

procedure Hide;

procedure MoveBy(dX, dY:Integer);

procedure MoveTo(NewX_,NewY_:Integer);

procedure Init(X_,Y_,:Integer);{процедура инициализации объекта}

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17