如果函数不是
static
的,你不能将其作为非成员函数指针传递给接受该指针类型的函数。
注意,一个非
static
成员函数有一个隐式指向
ClassName
的指针作为它的第一个参数,该指针指向调用该成员函数的对象。
struct X
{
static void foo() { }
void bar() { }
};
int main()
{
void (*f)() = &X::foo;
void (*g)() = &X::bar;
}
这里,即使使用std::bind()
也不起作用,因为结果无法转换为函数指针。Lambda表达式可以转换为函数指针,但仅限于非捕获的情况(并且此处的lambda表达式需要捕获对象以调用成员函数)。
因此,唯一(丑陋)的解决方法是拥有一个全局适配器函数,该函数在通过全局指针变量访问对象上调用成员函数。在调用函数之前设置全局指针变量:
struct X
{
void bar() { }
};
void function_taking_a_function_pointer(void (*f)())
{
f();
}
X* pX = nullptr;
void bar_adapter()
{
pX->bar();
}
int main()
{
X x;
pX = &x;
function_taking_a_function_pointer(bar_adapter);
}
如果您希望的话,可以将bar_adapter
转换为一个函数模板,通过将指向成员函数的指针作为模板参数传递来使其更加灵活:
template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}
以下是如何使用它的方法:
#include <iostream>
struct X
{
void foo() { std::cout << "X::foo()" << std::endl; }
void bar() { std::cout << "X::bar()" << std::endl; }
};
void function_taking_a_function_pointer(void (*f)())
{
f();
}
X* pX = nullptr;
template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}
int main()
{
X x;
pX = &x;
function_taking_a_function_pointer(adapter<X, &X::foo>);
function_taking_a_function_pointer(adapter<X, &X::bar>);
}
最后,这里有一个
实时示例。