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 method1run7 而不改变 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);
    }