Нет ничего плохого в использовании указателей на функции. Однако указатели на нестатические функции-члены не похожи на обычные указатели на функции: функции-члены должны вызываться для объекта, который передается в качестве неявного аргумента функции. Подпись вашей функции-члена выше, таким образом
void (aClass::*)(int, int)
а не тот тип, который вы пытаетесь использовать
void (*)(int, int)
Один из подходов может заключаться в создании функции-члена, и static
в этом случае она не требует вызова какого-либо объекта, и вы можете использовать ее с типом void (*)(int, int)
.
Если вам нужно получить доступ к любому нестатическому члену вашего класса, и вам нужно придерживаться указателей функций, например, поскольку функция является частью интерфейса C, ваш лучший вариант - всегда передавать a void*
вашей функции, принимая указатели на функции и вызывать ваш член через функцию пересылки, которая получает объект из, void*
а затем вызывает функцию-член.
В правильном интерфейсе C ++ вы можете захотеть посмотреть, как ваша функция принимает шаблонный аргумент для объектов функции, чтобы использовать произвольные типы классов. Если использование шаблонного интерфейса нежелательно, вы должны использовать что-то вроде std::function<void(int, int)>
: вы можете создать соответствующий вызываемый объект функции для них, например, используя std::bind()
.
Типобезопасные подходы с использованием аргумента шаблона для типа класса или подходящего std::function<...>
предпочтительнее, чем использование void*
интерфейса, поскольку они устраняют возможность ошибок из-за приведения к неправильному типу.
Чтобы прояснить, как использовать указатель функции для вызова функции-члена, вот пример:
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, 0);
foo object;
somefunction(&forwarder, &object);
}