passing member functions as parameters / c++

会有一股神秘感。 提交于 2019-12-23 13:53:48

问题


I would like to implement, in c++, a class b where it would be possible to do some kind of iteration through a member set encapsulating the type of that iterator. Like:

b_object.for_each_x_do(function_f);

so function_f would get everyone of the x members and do anything. Let's say:

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

Ok. So I'm trying to achieve that through a code like:

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(){} 

However, I'm getting this error, compile-time:

fp.cpp: In constructor ‘a::a()’:
fp.cpp:17: error: no matching function for call to ‘b::foreach_x_do(<unresolved overloaded function type>)’
fp.cpp:6: note: candidates are: void b::foreach_x_do(void (*)(int))

Anybody can help getting it to compile?


回答1:


It should just be:

b_inst.foreach_x_do(f);

You also need to make f static, not a non-static member method since the original signature for your foreach_x_do function is for a stand-alone function pointer, not a pointer-to-member-function. So i.e.,

static void f(int x) {  } 



回答2:


As @steveo225 noted, f in that context is of type void (a::*)(int) rather than void (*)(int). There are two approaches to fixing this -- the first is to make b::foreach_x_do a member function template that takes any callable type:

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

The second is to keep b::foreach_x_do a non-template and have it take a std::function<> instead of a function pointer:

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

In either case, replace std::bind and std::function with their boost:: counterparts if your compiler is too old to ship with std:: or std::tr1:: implementations. Also note that if you have a C++11 compiler, you can use a lambda instead of bind.




回答3:


The function for_each_x_do is expecting a function pointer, while you're (trying) to give it a member function pointer. The two are not the same. The former can be called directly, while the latter requires an object instance to be called. I'd suggest you use std::function or boost::function instead. Something like:

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

And then use a binder to construct a function object:

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



回答4:


In this line:

 b_inst.foreach_x_do(f)();

Remove the second set of parenthesis; you don't need them.

 b_inst.foreach_x_do(f);

should work fine.




回答5:


f() is a member function -- so it's relevance is limited to it's corresponding object. Some of these solutions so far won't work.

You have two choices, either make the function static, in which case it doesn't matter which object, or somehow also pass the object.

The second method is clearly explained in this helpful FAQ specifically about passing member functions.




回答6:


Try:

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

};



来源:https://stackoverflow.com/questions/6063112/passing-member-functions-as-parameters-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!