将成员函数作为参数 / C++ 传递

passing member functions as parameters / c++

本文关键字:C++ 传递 参数 成员 函数      更新时间:2023-10-16

我想在 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))

有人可以帮助编译它吗?

正如@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::std::tr1::实现一起提供,请将 std::bindstd::function 替换为其boost::对应项。另请注意,如果您有 C++11 编译器,则可以使用 lambda 而不是 bind

它应该只是:

b_inst.foreach_x_do(f);

您还需要f静态而不是非静态成员方法,因为 foreach_x_do 函数的原始签名是用于独立函数指针,而不是指向成员函数的指针。 所以即,

static void f(int x) {  } 
函数

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

在这一行中:

 b_inst.foreach_x_do(f)();

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

 b_inst.foreach_x_do(f);

应该工作正常。

f() 是一个成员函数 - 因此它的相关性仅限于其相应的对象。 到目前为止,其中一些解决方案将不起作用。

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

第二种方法在此有用的常见问题解答中进行了明确说明,特别是有关传递成员函数的信息。

尝试:

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

};