c++: callback или нет?

В раздумьях я.

Есть фунция Save, которая принимает некую структуру с описанием того, что нужно сохранить.
В этой структуре есть сведения о том как рассчитать то, что нужно сохранить.
Есть функции расчёта, они принимают разные параметры и возвращают разные типы.
По хорошему, надо использовать callback'и, но это же невозможно для разнотипных функций. Или возможно?
такие дела.
Я давно отошел от прикладного программирования, поэтому на абсолютную истину не претендую.
Но раз мы раздумываем в области применения C++, то я бы сделал иначе: нужен базовый класс, содержащий виртуальную функцию для рассчета. А в производных классах реализовывать для каждого с нужным числом и типом параметров. Как-то так, если я правильно представил себе задачу.
Спасибо за совет. Идея наверное правильная, но в данном конкретном случае функции расчёта это инлайновые (по сути своей) формулы и городить под них классы это, мягко говоря, оверкиль. К тому же Save это метод большого класса из данных которого вычисления и производятся.

Для большей ясности поясню.
Есть базовая физическая величина, которая рассчитывается в цикле, но она сама по себе не слишком интересна и интерпретировать её на глазок тяжело, поэтому из неё периодически вычисляются более привычные человеку физ.величины посредством достаточно простых формул.
такие дела.
Похоже, имеется небольшая путаница в понятиях. Зачем вообще заводится речь о методе Save? Для объектов класса, которыми он оперирует, он должен выглядеть таким же методом, как и методы, вычисляющие определенные характеристики (в нашем примере физические величины) класса. То есть, либо модифицируете исходный класс, добавляя нужные методы, либо создаете производный с необходимыми свойствами. А методы вычисления физ. величин реализуете одним из способов: либо несколько индивидуально именуемых, либо, если логика объекта позволяет, с одинаковым именем, но перегруженных по принимаемым параметрам (owerloading).

В этой структуре есть сведения о том как рассчитать то, что нужно сохранить

Язык C собственными средствами должен какие-то формулы преобразовывать в свой код или в вызов функции? Экономьте время, не надо писать, что я неправильно понял.

Выше однозначно указали, как это может делать C, вы же хотите с его помощью в одной процедуре решить задачу намного более сложную, чем исходная.
kurych,
Класс один. Проще конечно псевдокод показать ;) Схема примерно такая:

TModel
{
....
 double CalcQuantityA(int x, int y, int z);
 double CalcQuantityB(int x, int y);
 some_data_type CalcQuantityС(int x, int y, int z);

 Save(SaveStruct* sd);
}

struct SaveStruct
{
 QuanityID id; // что надо: A,B или C (enum)
 int x,y,z ;
}

TModel::Save(SaveStruct* sd)
{
 и вот тут либо тупо свитчить sd->id или как-то красиво коллбэк CalcQuantity*() сделать.
 а потом в файл писать
}
такие дела.
В данном случае красиво сделать коллбэк, как сами понимаете, не получится, т.к. в приведенном примере и возвращаемые типы разные и количество аргументов непредсказуемо. И owerloading function использовать нельзя, т.к. CalcQuantityA и CalcQuantityС, например, имеют одинаковый набор параметров.
Поэтому да, самое логичное использовать обычный селектор по id. А если не прибегать к каким-нибудь специфическим костылям, то вроде как и единственное решение.
PS: Попробуйте описать объекты, с которыми оперируете, с использованием понятия полиформизма в C++. Я именно это имел в виду, когда упоминал виртуальные функции. Мне это представляется наиболее последовательным решением при использовании языка ООП.
kurych, спасибо за консультацию. В итоге так и сделал, хотя выглядит некрасиво и имеется небольшая копипаста.

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

PS Кстати как вариант:

void CalcQuantity(void* retval, int x, int y, int z=0);
Но тогда свитч передвинется из Save'а в эту функцию...
такие дела.
В этом и заключается искусство, когда из множества доступных вариантов надо выбрать самый подходящий. ;-)
Всегда приходится выбирать какой-то компромисс и неверно выбранное решение в дальнейшем приводит к необходимости рефакторинга кода. Обычно, если это одноразовая задача, то чем проще написано, тем лучше. Если предполагается продолжительное использование в качестве библиотечки, то есть смысл заморочиться и сделать удобный и прозрачный интерфейс (извиняюсь за банальность).
Просто навскидку еще вариантики на разные вкусы: private void CalcQuantity(); - незачем передавать параметры, т.к. функция и так имеет доступ к переменным собственного класса. При этом вычисляемые величины можно также хранить в классе по отдельности, а можно, для экономии места, "поселить" в unit.
Впрочем, все подобные нюансы дело исключительно вкуса, о котором трудно спорить. И мне очень близка и понятна ваша тяга к красивому решению. ;-) Желаю удачи!
kurych
private void CalcQuantity(); - незачем передавать параметры, т.к. функция и так имеет доступ к переменным собственного класса. При этом вычисляемые величины можно также хранить в классе по отдельности, а можно, для экономии места, "поселить" в unit.

Ирония в том, что именно от этого решения я и пытаюсь уйти ;) Это хорошо работало на небольших сетках, а вот на больших стало капитальным тормозом. Хочется из писишки выжать ещё капельку, прежде чем на кластер вылезать. Там свои заморочки.
такие дела.
 
Зарегистрироваться или войдите чтобы оставить сообщение.