2011-05-19 101 views
4

我想在C++中实现一个类b其中可以通过封装该迭代器类型的成员集进行某种迭代。像:传递成员函数作为参数/ C++

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: 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))

任何人都可以帮得到它来编译?

+2

首先,传递给'foreach_x_do'的'f'不是'void(*)(int)'它是'void(a :: *)(int)'。 – steveo225 2011-05-19 18:26:01

+1

只是一个旁注,你应该用大写命名你的类。所以'B类'而不是'B类'。只是为了符合常见的消息。 – Falmarri 2011-05-19 18:29:54

+1

[此常见问题](http://www.parashift.com/c++-faq-lite/pointers-to-members.html)将为您提供比您想要了解的有关传递成员函数更多的信息。 – jedwards 2011-05-19 18:37:45

回答

1

应该仅仅是:

b_inst.foreach_x_do(f); 

你也需要做出f静态的,不是一个非静态成员方法,因为你foreach_x_do功能的原始签名是一个独立的函数指针,而不是一个指针到成员函数。如此即

static void f(int x) { } 
+0

我不知道是否有任何陷阱与此解决方案(因为该方法变成静态),但对于我的简单任务,它的效果很好。也许使用bind()的解决方案更好,但我喜欢这个,因为它更独立于编译器。 – ribamar 2011-05-19 21:28:49

+0

主要的“陷阱”是静态函数不能直接访问类的非静态成员或方法......所以如果你需要访问一个非静态的数据成员或方法,你必须通过一个引用或指向类对象的指针作为函数的参数。 – Jason 2011-05-20 01:54:44

0

在这一行:

b_inst.foreach_x_do(f)(); 

卸下第二组括号;你不需要它们。

b_inst.foreach_x_do(f); 

应该可以正常工作。

-2

尝试:

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

};

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));  
} 
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 eir boost::同行如果您的编译器太旧,无法使用std::std::tr1::实现。另请注意,如果您有C++ 11编译器,则可以使用lambda代替bind

0

f()成员函数 - 因此它的相关性仅限于它的相应对象。目前为止,这些解决方案中的一些将无法使用

你有两个选择,要么使函数静态,在这种情况下,哪个对象或某种方式也传递对象并不重要。

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

相关问题