如果函数不是static
,则不能将其作为输入传递给接受非成员函数指针的函数。
考虑一个非static
成员函数有一个隐式指针ClassName
作为它的第一个参数,它指向调用成员函数的对象。
struct X
{
static void foo() { } // Does not have an implicit "this" pointer argument
void bar() { } // Has an implicit "this" pointer argument
};
int main()
{
void (*f)() = &X::foo; // OK: foo is static
void (*g)() = &X::bar; // ERROR! bar is non-static
}
在这里,甚至std::bind()
不起作用,因为结果不能转换为函数指针。Lambda 可以转换为函数指针,但前提是它们是非捕获的(这里的 lambda 需要捕获对象以调用成员函数)。
因此,唯一(丑陋的)解决方法是拥有一个全局适配器函数,该函数调用对象上的成员函数,该对象可通过全局指针变量获得。全局指针变量在调用函数之前设置:
struct X
{
void bar() { }
};
void function_taking_a_function_pointer(void (*f)())
{
// Do something...
f();
}
X* pX = nullptr;
void bar_adapter()
{
pX->bar();
}
int main()
{
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function...
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)())
{
// Do something...
f();
}
X* pX = nullptr;
template<typename T, void (T::*mf)()>
void adapter()
{
(pX->*mf)();
}
int main()
{
X x; // Some object I want to invoke the member function bar() on...
pX = &x; // Set the global pointer and invoke the function(s)...
function_taking_a_function_pointer(adapter<X, &X::foo>);
function_taking_a_function_pointer(adapter<X, &X::bar>);
}
最后,这是一个活生生的例子。