Нет ничего плохого в использовании указателей на функции. Однако указатели на нестатические функции-члены не похожи на обычные указатели функций: функции-члены необходимо вызывать для объекта, который передается функции в качестве неявного аргумента. Подпись вашей функции-члена выше, таким образом,
void (aClass::*)(int, int)
а не тип, который вы пытаетесь использовать
void (*)(int, int)
Один из подходов может состоять в том, чтобы сделать функцию-член static
, и в этом случае она не требует вызова какого-либо объекта, и вы можете использовать ее с типом void (*)(int, int)
.
Если вам нужно получить доступ к любому нестатическому члену вашего класса и вам нужно придерживаться указателей функций, например, поскольку функция является частью интерфейса C, лучше всего всегда передавать 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, nullptr);
foo object;
somefunction(&forwarder, &object);
}
person
Dietmar Kühl
schedule
30.09.2012