Распространенной идиомой C ++ является использование функторов (то есть объектов, которые переопределяют operator ()). Дело в том, что вы используете один объект для инкапсуляции как кода, который необходимо вызвать, и данных, на которые будет воздействовать этот код. Независимо от того, выполняется ли функтор вручную или генерируется с помощью boost :: bind и / или , вероятно, не имеет большого значения для накладных расходов времени выполнения.
Так что вместо:
typedef void (*cb)(void*);
void funcThatNeedsCallback(cb thecallback, void *thedata) {
// blah blah
thecallback(thedata);
}
сделать:
template<typename T>
void funcThatNeedsCallback(T &thefunctor) {
// blah blah
thefunctor();
}
Тогда звонящий делает:
struct MyFunctor {
int mydata1;
char *mydata2;
void operator()(void) {
// do something with mydata1 and mydata2
}
};
MyFunctor mf = { value1, value2 };
funcThatNeedsCallback(mf);
Очевидно, что если вы предпочитаете, вы можете сделать члены частными и передать их конструктору, а не использовать список инициализаторов.
Если вы беспокоитесь о шаблонах (например, если funcThatNeedsCallback содержит много кода, который дублируется), то используйте абстрактный класс для определения виртуального метода, который должен иметь параметр, и используйте этот метод в качестве обратного вызова:
class CallbackInterface {
virtual void theCallback(void) = 0;
virtual ~CallbackInterface() {} // just in case
};
void funcThatNeedsCallback(CallbackInterface &cb) {
// blah blah
cb.theCallback();
}