传递成员函数作为参数/ c ++

时间:2011-05-19 18:20:37

标签: c++ member-function-pointers

我想在c ++中实现一个类 b ,在那里可以通过封装迭代器类型的成员集进行某种迭代。喜欢:

b_object.for_each_x_do(function_f);

所以 function_f 会让 x 成员的每个人都做,并做任何事情。让我们说:

void function_f(x_member_type x){ cout << x << endl; }

确定。所以我试图通过以下代码实现这一目标:

class b{
    int *x;
public:
    void foreach_x_do(void (*f)(int)){
            while(*x++)  // or any kind of iteration through x
                    f(*x);
    }
};

class a{
    b b_inst;
public:
    void f(int x) {  }     
    a(){
            b_inst.foreach_x_do(f); // by mistake it was b_inst.foreach_x_do(f)(), however this wasn't the point at all. 
    }
    ~a(){}
};

int main(){} 

但是,我收到了这个错误,编译时间:

  

fp.cpp:在构造函数‘a::a()’中:
  fp.cpp:17:错误:没有用于调用‘b::foreach_x_do(<unresolved overloaded function type>)’的匹配函数
  fp.cpp:6:注意:候选人是:void b::foreach_x_do(void (*)(int))

有人可以帮忙把它编译好吗?

6 个答案:

答案 0 :(得分:2)

正如@ steveo225所指出的那样,该上下文中的f类型为void (a::*)(int)而不是void (*)(int)。有两种方法可以解决这个问题 - 第一种方法是使b::foreach_x_do成为采用任何可调用类型的成员函数模板:

class b {
    int* x;

public:
    b() : x() { }
    template<typename F>
    void foreach_x_do(F f) {
        while(*x++)
            f(*x);
    }
};

class a {
    b b_inst;

public:
    void f(int x) { }
    a() : b_inst() {
        b_inst.foreach_x_do(std::bind(&a::f, this, _1));
    }
};

第二个是让b::foreach_x_do保持非模板,并使用std::function<>而不是函数指针:

class b {
    int* x;

public:
    b() : x() { }
    void foreach_x_do(std::function<void(int)> const& f) {
        while(*x++)
            f(*x);
    }
};

class a {
    b b_inst;

public:
    void f(int x) { }
    a() : b_inst() {
        b_inst.foreach_x_do(std::bind(&a::f, this, _1));
    }
};

在任何一种情况下,如果您的编译器太旧而无法提供std::bindstd::function实施,请将boost::std::替换为std::tr1::对应项。另请注意,如果您有C ++ 11编译器,则可以使用lambda而不是bind

答案 1 :(得分:1)

应该是:

b_inst.foreach_x_do(f);

您还需要使f静态,而不是非静态成员方法,因为foreach_x_do函数的原始签名是针对独立函数指针,而不是指向成员的指针-功能。那就是,

static void f(int x) {  } 

答案 2 :(得分:1)

函数for_each_x_do期待一个函数指针,而你(尝试)给它一个成员函数指针。两者不一样。前者可以直接调用,而后者需要调用对象实例。我建议您改用std::functionboost::function。类似的东西:

void for_each_x_do(function<void (int)> f) {
  // your code here
}

然后使用绑定器构造一个函数对象:

a(){
  b_inst.foreach_x_do(bind(&a::f, this, _1));     
}

答案 3 :(得分:0)

在这一行:

 b_inst.foreach_x_do(f)();

删除第二组括号;你不需要它们。

 b_inst.foreach_x_do(f);

应该可以正常工作。

答案 4 :(得分:0)

f()是一个成员函数 - 所以它的相关性仅限于它的相应对象。到目前为止,其中一些解决方案无效。

你有两个选择,要么将函数设为静态,在这种情况下,哪个对象无关紧要,或以某种方式传递对象。

第二种方法在this helpful FAQ中明确解释了传递成员函数。

答案 5 :(得分:-2)

尝试:

class b{
int *x;
public:
void foreach_x_do(void (*f)(int)){
        while(*x++)  // or any kind of iteration through x
                (*f)(*x);
}

};