C++ 将另一个方法作为参数传递
C++ pass another method as argument
在下面显示的简单代码中,有一个函数 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);
^
我想调用 pass 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;
}
制作 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);
}
如果仔细查看错误:
error: cannot convert ‘A::method1’ from type ‘void (A::)(int)’ to type ‘void (*)(int)’
您会发现类型不同。那是因为 class 方法与原始函数的类型不同——它们需要额外的对象才能被调用。无法编译该代码,因为调用 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
}
还有另外两种方法:
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);
}
在下面显示的简单代码中,有一个函数 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);
^
我想调用 pass 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;
}
制作 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);
}
如果仔细查看错误:
error: cannot convert ‘A::method1’ from type ‘void (A::)(int)’ to type ‘void (*)(int)’
您会发现类型不同。那是因为 class 方法与原始函数的类型不同——它们需要额外的对象才能被调用。无法编译该代码,因为调用 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
}
还有另外两种方法:
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);
}