在下面显示的简单代码中,有一个函数run7
,它接收函数作为参数。在main
函数中,函数test
被传递给它,它工作正常。但是,我的method2
无法将method1
传递给此函数。它会导致错误:
main.cpp:24:15: error: cannot convert ‘A::method1’ from type ‘void (A::)(int)’ to type ‘void (*)(int)’
run7(method1);
^
我想将method1
传递给run7
,而不更改run7
的结构。如何修复method2
?
#include <iostream>
using namespace std;
void run7 ( void (*f)(int) )
{
f(7);
}
void test(int a)
{
cout<<a<<endl;
}
class A
{
public:
int m=4;
void method1(int a)
{
cout<< a*m <<endl;
}
void method2()
{
run7(method1);
}
};
int main()
{
run7(test);
return 0;
}
答案 0 :(得分:4)
如果仔细观察错误:
错误:无法将'A :: method1'从类型'void(A ::)(int)'转换为'void(*)(int)'
您会看到类型不同。这是因为类方法与原始函数的类型不同 - 它们需要额外的对象才能被调用。没有办法让代码编译,因为调用method1
需要A
,这需要存储,这是不可能作为原始函数指针传入的。
您可以做的是更改run
以使用类型删除的仿函数:
void run7 ( std::function<void(int)> f ) {
f(7);
}
然后传入一个也传入this
:
void method2()
{
run7(std::bind(&A::method1, this, // option 1
std::placeholders::_1));
run7([this](int x){ this->method1(x); }); // option 2
}
答案 1 :(得分:2)
使run7
成为一个函数模板,以便它可以使用任何可调用对象。
template <typename F>
void run7(F f)
{
f(7);
}
然后,使用lambda函数从method2
调用它。
void method2()
{
run7([=](int arg){this->method1(arg)];});
}
<强>更新强>
您可以使用更好的run7
版本,它使用通用引用并完美转发以使其清晰(感谢@Quentin提供的建议)。
template <typename F>
void run7(F&& f)
{
std::forward<F>(f)(7);
}
答案 2 :(得分:0)
这是另外两种方式:
template <typename T>
void run7 (T & object, void (T::*method)(int))
{
(object.*method)(7);
}
或:
template <typename Class, typename Method>
void run7 (Class & object, Method && method)
{
(object.*method)(7);
}
无论哪种方式,呼叫站点都将如下所示:
void method2()
{
run7(*this, &A::method1);
}