delphi передать процедуру как параметр

Delphi передать процедуру как параметр

Данная с татья посвящена передаче функции в качестве параметра в другую функцию / процедуру.

Необходимо было реализовать вычисление определенных интегралов 20 функций методами трапеций и прямоугольников. Если реализовывать поставленную задачу, то для каждой реализуемой функции необходимо было запрограммировать каждый метод отдельно. Поэтому возник закономерный вопрос: А нельзя-ли запрограммировать каждую функцию, которую надо интегрировать, отдельно, и методы интегрирования отдельно, а после этого передавать в методы интегрирования интегрируемую функцию в качестве параметра.

Изучая данный данный вопрос в Интернете на большинстве сайтов размещена статья « Передача функции как параметра« (одна из первых ссылок на сайте delphiworld). Основные недостатки статьи: это привязка к DLL и вызов функции в общем виде.

На одном из форумов нашел понятное объяснение которое в итоге и реализовал.

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

type
TMyFuncType = function (xn:double) : double;

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

Далее вводим переменную пользовательского типа TMyFuncType:

var
MyFunc:TMyFuncType;

данную переменную вводим для того, чтобы сохранить имя одной из выбранных функций (одну из 20 функций), которую надо интегрировать, для последующей передачи в выбранный метод интегрирования трапеций или прямоугольников.

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

function rectangle1(var a,b:double; n:integer; MyFunc1:TMyFuncType): double; //метод прямоугольников
var
xn: array of double;
sum,h :double;
i:integer;
begin
SetLength(xn, n);
xn[0] := a;
h:= (b-a)/n;
sum := MyFunc1(xn[0]); //Вызов передаваемой функции
for i:=1 to n-1 do begin
xn[i] := xn[i-1]+h;
sum := sum + MyFunc1(xn[i]);
//Вызов передаваемой функции
end;
Result := sum*h;
end;

В параметрах передаваемых функции следует обратить внимание на параметр MyFunc1:TMyFuncType, который обеспечивает передачу имени одной из выбранных функций в качестве параметра функции. При этом вызов передаваемой функции осуществляется стандартным образом

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

c := rectangle1(a, b, n, MyFunc);

Таким образом в данной статье на конкретном примере (код функции интегрирования методом прямоугольников ) была рассмотрена возможность передачи функции в качестве параметра в другую функцию / процедуру, которая обеспечивает гибкость при программировании, а также позволяет уменьшить количество написанного кода.

Источник

Передача процедур и функций в качестве параметров

Помощь в написании контрольных, курсовых и дипломных работ здесь.

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

С++ Использование функций как параметров процедур
Процедура Р формирует массив из элементов Z, для которых одновременно выполняются условия F1( Z)>C.

Директивы и соглашения вызова процедур и передача параметров
Здравствуйте. Сразу говорю что не наглею, а прошу помощи в решении задачи: Задача: Логика работы.

Передача файлов в качестве параметров
Необходимо передать файловую переменную как параметр. При передаче выдает переполнение стека, не.

2. Чаще всего перадаются просто указатели на функцию, вроде CallBack функций.

Тоесть, если function TheFunction (progress: longint): boolean;

Пишешь указатель SomeRoutine (a,b, @TheFunction); в качестве параметра.

посмотри пример кода здесь

Если правильно понял, то тип должен быть Pointer. Поправьте меня, если это не так.
Всё это хорошо, но моей ситуации мне нужно передавать в качестве параметров не функцию, а процедуру. Скажите, это возможно и если да, то как как это реализовать?

Пытался так
Дальше в процедуре SomeRoutine пытаюсь вызвать функцию TheFunction так:

Ссылка на видеоурок по этой теме:

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Использование функций в качестве формальных параметров
Помогите вычислить f(x)/g(x), где в качестве f(x) и g(x) могут быть четыре различные функции.

Передача чисел в качестве параметров функции
Привет, нужна ваша помощь! Вычислить произведение целых чисел, переданных в качестве параметров.

Передача массивов в качестве параметров функции
Задав динамический двумерный массив вещественных данных (матрицу А размером NxN), реализовать его.

Обработать одномерный массив с использование процедур и функций без параметров и с параметрами
После первого элемента вставить 0 Обработать одномерный массив с использование процедур и функций.

Источник

Использование процедур и функций в Delphi

Скобки

Добавление скобок при вызове процедур и функций без параметров уже давно не является новинкой в Delphi, тем не менее, эта возможность мало известна. Эту возможность оценят по достоинству те программисты, которым приходится работать на двух языках (C++ и Delphi), так как им не нужно будет постоянно помнить о разнице в синтаксисе при вызове процедур и функций в разных языках. В Delphi оба варианта, приведенные ниже, считаются корректными.

Читайте также:  Что такое привоз у евреев

Возможность перегрузки

Впервые концепция перегрузки процедур и функций была реализована в Delphi 4. Она позволяет иметь несколько различных процедур и функций с одинаковыми именами, но с разными списками параметров. Такие процедуры и функции должны быть описаны с применением директивы overload.

procedure Test (I: integer); overload;
procedure Test (S: string); overload;
procedure Test (D: double); overload;

При вызове процедуры Test, Delphi сама решит, какую из трех процедур необходимо выполнить, в зависимости от передаваемого ей параметра. Но нужно отметить, что это не самая безопасная возможность языка. Применение перегружаемых процедур и функций может стать неиссякаемым источником трудноуловимых ошибок в программе. Поэтому пользуйтесь этой возможностью осторожно.

Передача параметров

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

Передача параметров по значению

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

procedure Test(s: string);

При вызове указанной процедуры будет создана копия передаваемой ей в качестве параметра строки s, с которой и будет работать процедура Test. При этом все внесенные в строку изменения никак не отразятся на исходной переменной s.

Однако это не относится к объектам. Например, если в функцию передается переменная (а точнее экземпляр объекта) TStringList, то в данном случае произойдет передача по ссылке (даже если это не указано явно). Этот способ передачи является у большинства самым излюбленным, но в тоже время является и самым не практичным, т.к. для выполнения метода выделяется дополнительная память для создания точной копией передаваемой переменой. Для решения этой проблемы следует использовать один из способов описанных ниже.

Передача параметров по ссылке

Pascal позволяет также передавать параметры в функции или процедуры по ссылке — такие параметры называются параметрами-переменными. Передача параметра по ссылке означает, что функция или процедура сможет изменить полученные значения параметров. Для передачи параметров по ссылке используется ключевое слово var, помещаемое в список параметров вызываемой процедуры или функции.

procedure ChangeMe(var x: longint);
begin
x := 2; // Параметр х изменен вызванной процедурой
end;

Вместо создания копии переменной x, ключевое слово var требует передачи адреса самой переменной x, что позволяет процедуре непосредственно изменять ее значение.

Передача параметров констант

Если нет необходимости изменять передаваемые функции или процедуре данные, можно описать параметр как константу. Ключевое слово const не только защищает параметр от изменения, но и позволяет компилятору сгенерировать более оптимальный код передачи строк и записей. Вот пример объявления параметра-константы:

procedure Test(const s: string );

Передача открытых массивов

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

function AddEmUp(A: array of integer): integer;

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

Для получения информации о фактически передаваемом массиве параметров в функции или процедуре могут использоваться функции High, Low и SizeOf.

Object Pascal также поддерживает тип array of const, который позволяет передавать в одном массиве данные различных типов. Синтаксис объявления функций или процедур, использующих такой массив для получения параметров, следующий:

procedure WhatHaveIGot( A: array of const );

Вызвать объявленную выше функцию можно, например, с помощью такого оператора:

procedure WhatHaveIGot( [‘Text’, 10, 5.5, @WhatHaveIGot, 3.14, true, ‘c’] );

При передаче функции или процедуре массива констант все передаваемые параметры компилятор неявно конвертирует в тип TVarRec. Тип данных TVarRec объявлен в модуле System следующим образом:

PVarRec = ^TVarRec;
TVarRec = record
case Byte of
vtInteger: (VInteger: Integer; VType: Byte);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: Char);
vtExtended: (VExtended: PExtended);
vtString: (VString: PShortString);
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: PChar);
vtObject: (VObject: TObject);
vtClass: (VClass: TClass);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
vtAnsiString: (VAnsiString: Pointer);
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
end;

Поле VType определяет тип содержащихся в данном экземпляре записи TVarRec данных и может принимать одно приведенных значений.

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

Читайте также:  мирамистин или оки что лучше

procedure WhatHaveIGot( A: array of const );
var
i: integer;
TypeStr: string;
begin
for i := Low(A) to High(A) do
begin
case A[i].VType of
vtInteger : TypeStr := ‘Integer’;
vtBoolean : TypeStr := ‘Boolean’;
vtChar : TypeStr := ‘Char’;
vtExtended : TypeStr := ‘Extended’;
vtString : TypeStr := ‘String’;
vtPointer : TypeStr := ‘Pointer’;
vtPChar : TypeStr := ‘PChar’;
vtObject : TypeStr := ‘Object’;
vtClass : TypeStr := ‘Class’;
vtWideChar : TypeStr := ‘WideChar’;
vtPWideChar : TypeStr := ‘PWideChar’;
vtAnsiString : TypeStr := ‘AnsiString’;
vtCurrency : TypeStr := ‘Currency’;
vtVariant : TypeStr := ‘Variant’;
vtInterface : TypeStr := ‘Interface’;
vtWideString : TypeStr := ‘WideString’;
vtInt64 : TypeStr := ‘Int64’;
end;
ShowMessage( Format( ‘Array item %d is a %s’, [i, TypeStr] ) );
end;
end;

Значения параметров по умолчанию

В Delphi есть одна очень полезная возможность — использование значений параметров по умолчанию. Она позволяет установить принимаемое по умолчанию значение параметра процедуры или функции. Это значение будет использоваться в тех случаях, когда вызов процедуры или функции производится без указания значения данного параметра. В объявлении процедуры или функции принимаемое по умолчанию значение параметра указывается после знака равенства, следующего после его имени. Поясним это на следующем примере:

procedure HasDefVal( s: string; i: integer = 0 );

Подобное объявление означает, что процедура HasDefVal может быть вызвана двумя путями. В первом случае — как обычно, с указанием обоих параметров:

procedure HasDefVal( ‘Hello’, 26 );

Во втором случае можно задать только значение параметра s, а для параметра i использовать значение, установленное по умолчанию:

procedure HasDefVal( ‘Hello’ );

function Add( I1, I2: integer ): integer;
begin
Result := I1 + I2;
end;

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

function Add( I1, I2: integer; I3: integer = 0 ): integer;
begin
Result := I1 + I2 + I3;
end;

Директива

Директива <$X->запрещает вызов функций как процедур (с игнорированием возвращаемого результата). По умолчанию этот режим включен (<$X+>). Так вот, запомните, использование переменной Result недопустимо при сброшенном флажке опции Extended Syntax, расположенном во вкладке Compiler диалогового окна Project Options, или при указании директивы компилятора <$X->.

В каждой функции языка Objecl Pascal существует локальная переменная с именем Result, предназначенная для размещения возвращаемого значения. Кроме того, вернуть значение из функции можно также путем присвоения значения переменной, имеющей то же имя, что и данная функция. Это стандартный синтаксис языка Pascal, сохранившийся от его предыдущих версий. При использовании в теле функции переменной с ее именем не забывайте, что существуют большие отличия в обработке этого имени — все зависит от того, где она расположена — в левой части оператора присвоения или же в любом другом месте текста функции. Если имя функции указано в левой части оператора присвоения, то предполагается, что назначается возвращаемое функцией значение. Во всех других случаях предполагается, что осуществляется рекурсивный вызов этой функции.

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

Источник

Параметры функций, процедур

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

Типы параметров процедуры и функции Delphi.

В процедуры можно передать следующие типы параметров:

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

Параметр – константа

Параметр передается в функцию как константа. Это значит, что это значение нельзя изменять, при определении функции необходимо использовать ключевое слово const.
Пример определения функции с параметром в виде константы

Ещё раз хочу обратить Ваше внимание на то, что константа ни в коем случае не должна меняться в теле процедуры.

Параметр – переменные

Если мы хотим изменить какую-либо переменную в ходе выполнения процедуры/функции Delphi, то нам нужно в объявлении, перед именем добавить ключевое слово var. Приведу пример:

Смотрите. Мы описали первую функцию MyF и, изменяя в её теле переменную i, мы будем изменять переменную, которую передали как параметр. Такой способ передачи параметра называется передачей параметра по ссылке. Сейчас все станет ясно. Для этого разберем процедуру pr. Мы задаем переменной x значение ноль, выводим его, чтобы убедиться в этом. Далее мы эту переменную передаем в функцию MyF, где в результате наш x увеличивается на единицу. Это произошло именно благодаря тому, что параметр функции MyF объявлен с ключевым словом var.

Выходные параметры

В Delphi есть тип параметра функции, который используется только для вывода значения. Объявляется такой тип при помощи директивы Out. Данная директива может использоваться только в функциях. Использование выходных параметров очень напоминает использование var, разница в том, что значение не может быть изменено подпрограммой. Выходное значение в Delphi используется для возврата дополнительных переменных из функции. Нужно это тогда, когда одной переменной Result не обойтись.

Источник

Delphi передать процедуру как параметр

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: 1
Всего: 0

Здравствуйте.
Меня интересует как в Delphi можно передать процедуру как параметр функции.
А если подробней то вот такой код для примера.

Код
procedure TestProc(var WndProc: TWndProc);
begin

Любитель-программер

Профиль
Группа: Участник Клуба
Сообщений: 7325
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 26
Всего: 146

Цитата(Ak47black @ 30.7.2007, 19:46 )
TWndProc = procedure(var message: TMessage)of object;

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: 1
Всего: 0

Эксперт

Профиль
Группа: Участник Клуба
Сообщений: 2937
Регистрация: 9.2.2004
Где: Москва

Репутация: 72
Всего: 111

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: 1
Всего: 0

Любитель-программер

Профиль
Группа: Участник Клуба
Сообщений: 7325
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 26
Всего: 146

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: 1
Всего: 0

Эксперт

Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76

Код
type
TWndProc = procedure (var VMessage: TMessage) of object;

var
Form10: TForm10;

procedure TestProc(AWndProc: TWndProc);
begin
if Assigned(AWndProc) then
begin
//парам-пам-пам
end;
end;

procedure TForm10.FormCreate(Sender: TObject);
var
lWndProc: TWndProc;
begin
lWndProc := WindowProc;
TestProc(lWndProc);
end;

Амеба

Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459

Цитата(Romikgy @ 30.7.2007, 21:54 )
ИМХО это говорит о том что эта процедура является частью объекта

Обсуждение действий администрации форума производятся только в этом форуме

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

Эксперт

Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: 1
Всего: 0

Bose, тут метод класса как я вижу.

Амеба

Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459

Обсуждение действий администрации форума производятся только в этом форуме

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

Эксперт

Профиль
Группа: Участник Клуба
Сообщений: 2937
Регистрация: 9.2.2004
Где: Москва

Репутация: 72
Всего: 111

Цитата
To get the memory address of a procedural variable (rather than the address stored in it), use @@. For example, @@F returns the address of F.

Эксперт

Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51

По-моему вы тут всё перемудрили с этими адресами.

Вот простейший 100% работающий код из моего проекта(упрощённый вариант):

Код
//объявляем Тип
TComponentProcedure = procedure(aComp: TComponent) of object;

// код процедуры. Именно эта процедура будет вызывать процедуру-параметр
procedure ForEachComponent(aParent: TComponent; aActionProcedure: TComponentProcedure);
var i:integer;
tmpCtrlList:TList;
begin
for i := 0 to aParent.ComponentCount-1 do
begin
aActionProcedure(aParent.Components[i]); // вот вызов процедуры-параметра
end;
end;

ForEachComponent вызывает процедуру-параметр aActionProcedure для каждого дочернего компонента aParent.

А вот так вот этим всем пользуюсь:

Код
type
TForm1 = class(TForm)
protected
// Callback procedure(TComponentProcedure) for ForEachComponent
procedure cpCheckAndFillImageList(aComp: TComponent);
public
procedure TestCallbackRun; // пример вызова
end;

procedure TForm1.cpCheckAndFillImageList(aComp: TComponent);
begin
if aComp.InheritsFrom(TImageList) then
begin
// какие-то действия над (aComp as TimageList)
end;

procedure TForm1.TestCallbackRun;
begin
// для каждого компонента формы запустить процедуру cpCheckAndFillImageList
ForEachComponent(self, cpCheckAndFillImageList);
end;

Аццкий Сотона

Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128

Цитата(Ak47black @ 30.7.2007, 20:46 )
procedure TestProc(var WndProc: TWndProc);

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »

[ Время генерации скрипта: 0.1567 ] [ Использовано запросов: 21 ] [ GZIP включён ]

Источник

Образовательный портал