C ++将另一个方法作为参数传递

时间:2015-01-15 23:04:03

标签: c++ function c++11 function-pointers

在下面显示的简单代码中,有一个函数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;
}

3 个答案:

答案 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);
    }