Передача математической зависимости
1636
10
Есть несколько неких математических зависимостей - функций - для расчета одной величины разными методами. Нужна такая реализация, при которой бы на основе каких-либо условий выбиралась та или иная функция (метод расчета). Основная сложность кроется в том, что содержание расчетов, соответствующих этим функциям заведомо не известно и должно передаваться программе через специальный интерфейс, принимающий параметры для расчета.
Так вот, каким образом передать в этот интерфейс (принимающую функцию), например, такое:
y = 2*x - 10

Может, стоит, использовать указатель на функцию? Подскажите, кто сталкивался с подобной задачей.
Что же является критерием для выбора той или иной функции (метода)? Можно и switch использовать.
Anomander
Да. C++, среда VS6.
Вообще, как я понял, для подобной реализации вполне приемлемо использовать указатель на функцию. Осталась единственная проблема, которую пока не знаю как решить - как прописать принимающей функции в качестве параметра указатель на функцию. При использовании ClassWizard'a вариант типа float y(float x, float (*func)(float xval)); не предусмотрен. А при попытке менять типы вручную возникают ошибки.
Во-первых, я все еще не понял тонкостей задания. Есть контроллер, который принимает некие параметры (фиксированный набор или произвольный?) и вызывает некую функцию (передается вместе с параметрами или должен сам выбрать?)

Во-вторых, какого рода ошибки вылазят?
Anomander
Есть контрол, функция(интерфейс) которого принимает:
а) аргумент функции(некоей мат. зависимости)
б) саму мат. зависимость

В основном коде прописывается зависимость в виде функции:

float y(float curx)
{
float yres = curx*curx;
return yres;
}

Там же объявляется указатель на эту функцию:
float (*ptr)(float x) = y;

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

ControlName->CalcFunc(2.15, ptr);


Теперь нужно принять это значение функцией контрола:
float CalcFunc(float xcur, float (*func)(float x))
{
float ydst = func(xcur);
return ydst;
}

Добавление функции, видной извне, в контрол (функции интерфейса) производится через ClassWizard VS6. Там необходимо указать типы входящих данных путем выбора из списка. Как сделать это для случая с float (*func)(float x)) мне совсем неясно.
Вот, собственно, формулировка вопроса.
1. Если вариантов функций немного, это классический вариант паттерна Strategy.

2. Если хочется поиметь любое выражение, то это Interpreter: распарсить строку по грамматике, поиметь AST-дерево и Command-ами/Visitor-ами его посчитать.
Simeon Koptelov
Думается, можно обойтись более простой реализацией. Неоднократно слышал положительные отзывы о design patterns, но в них я не секу.

Зато появилась мысль, сводящая проблему к менее объемной.

В общем так.
Функция интерфейса ActiveX-контрола ждет зависимости, по которой булет производится дальнейший расчет.

Из основной программы в контрол передается указатель она функцию, сконвернутый в int.

Примерно так:
float (*ptr)(float) = func; // func - функция, которую надо передать контролу

MyControl1->MyFunction((int)ptr);

Соответственно, теперь требуется на стороне контрола получить из переменной типа int значение типа "указатель на функцию".
Как такое осуществить? Был бы какой-нить char* - там понятно:

MyFunction(int myptr)
{
char* pp = (char*)myptr;
}

А указатель на функцию так просто, похоже, из адреса не получить.
Я сейчас проверить не могу, но могу дать такой совет - на ClassWizard забить, написать простой код ручками и посмотреть, что получится. Если нормально с английским, можно почитать здесь:
http://www.function-pointer.org/fpt.html#passPtr

P.S. Передача указателя, сконвертированного в int, покатит, но это уже лишнее.
Anomander
1. За линку спасибо, приятно было ознакомиться с хорошо структурированным материалом по теме. Однако принципиальных идей подчерпнуть не удалось - и так выполняю все по описанному там варианту передачи указателя на функцию в качестве аргумента.

2. При попытке забить на ClassWizard вручную аргументы (их типы) функции замечательно редактируются в cpp и h файлах проекта,
Там они после внесения изменений имеют вид:
float (*func)(float).
Однако в odl-файле, то есть там, где прописаны все эти выходы функций наружу (интерфейсы), ни в какую не канает вариант float (*func)(float)

Ошибка: error MIDL2094 : [id] attribute is required : [( Parameter 'func' ) ]

Блин, мне все равно думается, что можно таким способом реализовать данную функциональность. Тока как совладать с odl-связями?
Или подскажите кто-нить, как переконвертить адрес на указатель на функцию в сам указатель на функцию, то есть из int в float (*func)(float).