如何在C ++中将类的方法传递给另一个函数?

时间:2013-03-28 17:42:09

标签: c++ class function methods

假设我有一个类和一个函数

class A
{
    int a;
    int b;
    int mul()
    {
        return a+b;
    }
};
...

void func(int af, int bf, int (*fc)())
{
    ...
}

在main函数中,该函数应该使用A类的方法

int main
{
    A as;
    ...
    func(as.a, as.b, as.mul);
}

然而,我不能这样做,编译器一直告诉我,我正在传递

(int&, int&, 'unresolved overloaded function type') 

成为候选人的功能

(int, int, void(*)()).

为什么会这样,以及如何将类的方法传递给另一个函数?

哦,我想我应该让问题更清楚一些。 func(...)实际上是我正在研究的算法的函数。 class A是一个使用算法进行模拟的模型。所以我不认为我会在函数B中专门使用A的实例,而只是传递A的方法和组件并使用它们。


更新:有人提到在A类中使用静态方法。但是,这仍然是部分解决方案。使用静态方法mul()将迫使我声称a和b都是静态的。如果我必须使用A的多个实例,在我的main函数的每个实例中使用方法a,b不同,使用静态变量将会失败。

那么,是否有其他建议如何在不使用静态变量/方法的情况下解决这个问题?我记得在python等脚本语言中,传递任何类型的方法基本上都不是问题。为什么我不能在C ++中做类似的事情?或者C ++中是否有可以帮助我做到这一点的变通方法?

5 个答案:

答案 0 :(得分:4)

首先,mulA成员函数,因此您无法像调用全局函数或{{1}一样调用它成员函数:它需要一个调用该函数的对象:

static

这就是说,可以更改A::mul(); // ERROR! A a; a.mul(); // OK 的定义以接受指向成员函数的指针:

func

但是,单独更改 不会让您进步太多,因为您仍然没有传递应该调用成员函数的void func(int af, int bf, void (A::*fc)()) // ^^^^^^^^^^^^^^^ 的具体实例。换句话说,这将是非法的:

A

为了克服这个限制,你可以将一个fc(); // ERROR! 实例的引用或指针一起传递给A,并按以下方式调用它:

func

但是,如果void func(A* pA, int af, int bf, void (A::*fc)()) { ... (pA->*func)(); } 具有应该调用成员函数的对象作为参数传入,则不清楚func()af的目的是什么。

可能,如果您的bf成员函数不需要处理mul()的任何具体实例,并且您仍希望将其作为A的成员,则可以声明它作为A

static

这将使您对class A { int a; int b; static void mul(); // ^^^^^^ }; 的原始调用进行编译。但是,在这种情况下,不清楚这是否有意义,因为func()不接受任何参数这一事实表明它应该适用于mul()a成员它被调用的对象。

答案 1 :(得分:1)

您要做的是传递成员函数指针(A::mul)以及实例(a)本身。没有任何额外的代码,这并不容易。

成员函数指针不与实例绑定(它们仅表示函数本身,而不是要调用的实例)。它们的类型与类名一起描述。 A上具有func签名的成员函数指针的类型将如下所示:

void (A::*)()     // The type only, anonymous
void (A::*fc)()   // An actual function pointer with the name `fc`

要调用这样的函数,您必须使用以下语法,正如您所看到的,必须参与调用该函数的实例:

(a->*fc)();       // If a is of type A*
(a.*fc)();        // If a is of type A or A&

要把事情放在一起,你基本上有两种选择。

  1. 除了成员函数指针之外,还传递实例(作为指针,引用,const或可修改)。然后,调用该实例上的成员函数指针。

    你是函数的签名,实现将如下所示:

    void func(int af, int bf, void (A::*fc)(), A *a) {
        // When you want to call the function fc on a:
        (a->*fc)();
    }
    

    要拨打func,请使用以下代码:

    func(as.a, as.b, &A::mul, a);
    
  2. 将成员函数指针与实例一起转换为可以按原样调用的仿函数。最好使用std::mem_fnstd::bind1st来完成此操作。

    你是函数的签名,实现将如下所示:

    void func(int af, int bf, std::function<void()> fc) {
        // When you want to call the function fc:
        fc();
    }
    

    要拨打func,请使用以下代码:

    func(as.a, as.b, std::bind1st(std::mem_fn(&A::mul), a));
    

答案 2 :(得分:1)

mul是否为非静态成员,需要类型为A的对象才能调用它?在这种情况下,您需要传递指向成员的指针:

void func(int af, int bf, void (A::*fc)())
{ //                            ^^^  
    A a = whatever();
    (a.*fc)();
}

如果打算在没有对象的情况下调用它,那么它必须是static

答案 3 :(得分:1)

如果你真的想要将int (*fc)(int,int)void返回和另一个例子中给出的空参数列表)视为常规函数指针(我的意思是不是类成员函数的函数指针),你可以做以下内容使用A的功能并将其传递给func。关键是将mul声明为静态成员函数。我假设操作非常简单,比如乘法。

#include <iostream>
class A
{
public: //necessary otherwise not accessible in main
   int a;
   int b;
   A(int p1, int p2):a(p1),b(p2){} //assume you need to somehow pass a,b into mul
   static int mul(int p1, int p2)  {return p1*p2;};  //mul should be static
};

void func(int af, int bf, int (*fc)(int,int))  
//using void still work but you need to change declaration of mul in A
{
  int res = fc(af,bf);  
  cout << res <<endl;
}

int main()
{
  A as(2,4);
  func(as.a, as.b, &A::mul); //call A::mul, use as regular function pointer, output 8
  func(10,10, &A::mul); //will output 100
  return 0;
}

这样你就可以使用A的静态成员函数,它可以被常规函数指针指向。它与课堂内的ab无关。

答案 4 :(得分:1)

正如leemes所说,你可以用std::function来做这个,这也是我推荐的,但是看看你的编译器支持什么,如果有的话,你可以使用{{1并让它工作。以下示例适用于Visual Studio 2012(并且应该适用于启用了C ++ 11标志的较新版本的GCC,并且在VS 2010上可能有效,也可能无效)

std::bind

致电:

void func(int af, int bf, std::function<void()> fc)
{
    fc();
}

func(as.a, as.b, std::bind(&as::mul, &A)); 的较新版本会在检测到成员函数时为您执行std::bind部分。请参阅此处链接的文档:

std::function

std::bind