Немає нічого поганого у використанні функціональних покажчиків. Однак покажчики на нестатичні функції членів не схожі на звичайні покажчики функцій: функції члена потрібно викликати на об'єкт, який передається як неявний аргумент функції. Таким чином, є підпис функції вашого члена вище
void (aClass::*)(int, int)
а не тип, який ви намагаєтесь використовувати
void (*)(int, int)
Один із підходів може полягати в створенні функції-члена, і static
в цьому випадку він не вимагає викликати жоден об'єкт, і ви можете використовувати його з типом void (*)(int, int)
.
Якщо вам потрібно отримати доступ до будь-якого нестатичного члена вашого класу, і вам потрібно дотримуватися функціональних покажчиків, наприклад, оскільки функція є частиною інтерфейсу С, найкращим варіантом є завжди передавати функцію 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);
}