Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

вызов функций с разным количеством аргументов? [D7]


miha29 ©   (2004-07-29 13:12:00) 

Доброго дня.
Подскажите пожста, ответ на следующую проблему:

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

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

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

в разных классах -> с разным (!) количеством параметров.
Не получается сделать универсальный тип функции в параметрах метода бисекции, такой чтобы не

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

что я согласен :) - это сделать в каждом классе одну (!) функцию которая сделает необходимое

приведение по количеству параметров).

Изиняюсь за путанное объяснение. Я делаю так:
в первом модуле:

 TmMath = class
     eps: double;
    function bisect(f: tfunc; rmin, rmax, eps: double): double;
......
 end
function TMMath.bisect;
var i: integer;
   fmin, fmax, h: double;
   sign: boolean;
begin
  i:=0; sign:=false;
    while (abs(rmax - rmin) - eps>0) do begin
       h:=(rmin + rmax)/2.0;
//здесь может стоять функция не с одним аргументом, соответственно rmax, rmin векторного

//типа, но как быть с tfunc?
       fmin:=f(rmin); fmax:=f(h);
         if fmin*fmax<0 then begin sign:=true; rmax:=h end
            else rmin:=h;
    end;
     if not sign then begin result:=0; exit; end else result:=h;
end;

во втором модуле:

type
  tfunc = function(xi, T: double): double of object far;
в третьем модуле:
 TmLPhase = class (TmPhase)
    function dG(xi, T: double): double; override; //здесь такой же тип как и tfunc
...
 end;

 TmL1Phase = class (TmPhase)
    function dG(xi, T, h: double): double; override; //тоже нужно использовать бисекцию

//(tfunc здесь не проходит)
...
 end;

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

a:=mmath.bisect(mLPhase.dG, 0, 5, 1e-4);
b:=mmath.bisect(mL1Phase.dG, 0, 5, 1e-4); //несоответствие типа функции.....


dtm   (2004-07-30 15:03:00) [1]

А VarArray тут не поможет ?


GuAV   (2004-07-30 13:19:00) [2]


> нужно не передавать разное количество аргументов функции,
> а передавать в функцию-1 функцию-2 как аргумент, причем
> функция-2 в разных классах определена с разным кол-вом аргументов.

А как вызвать функцию-2 переданную как аргумент, если в разных классах она определена с разным кол-вом аргументов, и при этом нужно не передавать разное количество аргументов функции?


Sandman25   (2004-07-30 12:53:00) [3]

Лучше const x: array of double.
Если, конечно, не нужно изменять аргументы


GuAV   (2004-07-30 12:52:00) [4]

type tf = function(x: array of double): double of object;

в функциях f1, f2 вместо x1, x2, x3, ...  юзать x[0], x[1], x[2] ...

и тогда никого не надо приводить.
вызывать так: r:=fnc([a, b, c]);


miha2   (2004-07-30 12:46:00) [5]

еще уточню :)
нужно не передавать разное количество аргументов функции,
а передавать в функцию-1 функцию-2 как аргумент, причем функция-2 в разных классах определена с разным кол-вом аргументов.
Overload делать очень не хочется! (так уже сделано, но кривость и объем кода бесит)


miha2   (2004-07-30 12:41:00) [6]

наверное, я неконкретно выразился....

передавать массив в качестве аргумента - не пойдет, параметры передать не проблема, проблема в передаче функции (у которой может быть 1, 2 и т.д. аргументов) . Например:

type
tvec = array of double;
tf1 = function(x: double): double of object;
tf2 = function(x, x1: double): double of object;

var
function bisect(f: tf1; x: double): double;

function TMyObj.root(func: tf1; p: tvec): double;
begin
...
result:={мат метод - находит корень функции 1-й переменной}mmath.bisect(func, p[0]);
end;

function TMyObj.root(func: tf2; p: tvec): double;
var f2: tf1;
begin
...
{здесь как-то нужно преобразовать func в f2}{внутри бисекции происходит вызов функции одной переменной, можно было бы сделать указатель (еще вопрос как?) на нужный процедурный тип и потом просто подменять, но как тогда быть с передачей параметров?}
result:={мат метод - находит корень функции 1-й переменной}mmath.bisect(f2, p[1]);
end;


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


panov   (2004-07-29 18:41:00) [7]

А самое простое - передавать открытый массив в качестве параметра.


Анонимщик   (2004-07-29 18:27:00) [8]

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


panov   (2004-07-29 17:56:00) [9]

А если так, например:

function MyFunc(arg1: Double=0;arg2: Double=0;arg3: Double=0;arg4: Double=0;arg5: Double=0): Double;

Обращение:

MyFunc(10.1,2);
MyFunc(1);
MyFunc(1,1,1,1);

??


  (2004-07-29 17:47:00) [10]

Удалено модератором


TUser   (2004-07-29 13:24:00) [11]

overload
еще можно передавать множество или динамический массив


Reindeer Moss Eater   (2004-07-29 13:20:00) [12]

Параметрами что выступает, вещественные числа?

function MyFunction(const Data; AItemCount: Word) : TMyResult;


Наверх

Титульная страница Поиск, карта сайта Написать письмо