std::bind与std::function详解

std::bind

1、定义

bind(F f, T1 t1, T2 t2, ..., TN tN);

具体为:

bind(&要调用的函数,&对象, 要调用函数的参数1,要调用函数的参数2...,_1(bind函数的参数1),_2(bind函数的参数2)...)

注:如果bind的是一个非静态成员函数,第二个参数一定是一个该成员的一个指针,后面才是正常的参数。

2、bind使用形式

(1)bind(&f)()  假设f是一个全局函数,绑定全局函数并调用;

(2)bind (&A::f, A())()  假设A是一个构造函数为空的类,这个形式绑定了类的成员函数,故第二个参数需要传入一个成员(成员静态函数除外);

(3)bind (&A::f, _1)(new A()) 同上,效果是一样的,但是使用了占位符,使得没有固定的的对象,推荐。

注:使用的时候一定要注意指向的是没有this指针的函数(全局函数或静态成员函数),还是有this指针的函数。后面一种必须要用bind()函数,而且要多一个参数,因为静态成员函数与非静态成员函数的参 数表不一样,原型相同的非静态函数比静态成员函数多一个参数,即第一个参数this指针,指向所属的对象,任何非静态成员函数的第一个参数都是this指针。

3、示例

[objc]  view plain  copy
  1. #include <stdio.h>  
  2. #include <functional>  
  3.   
  4. using std::function;  
  5. using std::bind;  
  6.   
  7. int func(int x,int y) {  
  8.     printf("nimei x:%d y:%d\n", x, y);  
  9.     return 3;  
  10. }  
  11. int main() {  
  12.     printf("%d\n", bind<int>(&func, 34)());<span style="color:#ff0000;">//<int>可以没有,但后面的()必须要有</span>  
  13.     return 0;  
  14. }  

std::function

1、静态成员函数情况

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <iomanip>  
  3. #include <memory>  
  4. #include <functional>  
  5.   
  6. typedef   std::function<void(int)>   HandlerEvent;  
  7.   
  8. //定义一个成员变量  
  9. class Sharp  
  10. {  
  11. public:  
  12.     HandlerEvent handlerEvent;  
  13. };  
  14. //设置handlerEvent的值来动态装载事件响应函数  
  15. class Rectangle  
  16. {  
  17. private:  
  18.     std::string name;  
  19.     Sharp sharp;  
  20. public:  
  21.     void initial(void);  
  22.     const Sharp getSharp() const;  
  23.     static void onEvent(int param)  
  24.     {   
  25.         std::cout << "invode onEvent method,get parameter: " << param << std::endl;  
  26.     }  
  27. };  
  28. //类的实现方法  
  29. void Rectangle::initial()  
  30. {  
  31.     sharp.handlerEvent = HandlerEvent(&Rectangle::onEvent);   
  32.     std::cout << "invode initial function!" << std::endl;  
  33. }  
  34. const Sharp Rectangle::getSharp() const  
  35. {  
  36.     return sharp;  
  37. }  
  38.   
  39. //测试函数  
  40. int main(int argc, char *argv[]){  
  41.     std::cout << "hi: " << std::setw(50) << "hello world!" << std::endl;  
  42.     Rectangle rectangle;  
  43.     rectangle.initial();   
  44.     rectangle.getSharp().handlerEvent(23);    
  45.     std::cin.get();  
  46. }  
  47. //输出结果  
  48. /*hi:                                       hello world! 
  49.     invode initial function! 
  50.     invode onEvent method, get parameter : 23*/  


注:这里使用了静态成员函数,如果把Rectangle前面的static去掉这段代码不能工作,编译都不能通过,因为静态成员函数与非静态成员函数的参数表不一样,原型相同的非静态函数比静态成员函数多一个参数,即第一个参数this指针,指向所属的对象,任何非静态成员函数的第一个参数都是this指 针,所以如果把Rectangle前面的static去掉,其函数原型等效于下面的一个全局函数:void onEvent(Rectangle* this, int);

2、非静态成员函数情况

将上例中Rectangle::onEvent(int param)前的static去掉改为非静态成员函数,则进行动态绑定使得程序正常运行,将Rectangle::initial(void)的定义修改为:

void Rectangle::initial(){

    sharp.handlerEvent = std::tr1::bind(&Rectangle::onEvent,this,std::tr1::placeholders::_1/*因onEvent函数需要一个参数,所以用一占位符*/);

    std::cout << "invode initial function!" << std::endl;

}

这样,便动态装载函数成功。其它测试数据都不用进行修改。测试结果于上一样。

3、虚成员函数情况

对于虚成员函数的情况与上面第2节所说相同,仍然可以实现虑函数的效果。如果定义类Square继承自Rectangle,将 Rectangle::OnEvent重载,定义一个新的Square::OnEvent,Rectangle::initial中的函数不变,仍然使用Rectangle::OnEvent进绑定,则调用成员object.onEvent()时,具体执行Rectangle::OnEvent还是Square::OnEvent,看object所属对象的静态类型是Rectangle还是Square而定。

示例:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. #include <iomanip>  
  3. #include <memory>  
  4. #include <functional>  
  5.   
  6. typedef   std::function<void(int)>   HandlerEvent;  
  7.   
  8. //定义一个成员变量  
  9. class Sharp  
  10. {  
  11. public:  
  12.     HandlerEvent handlerEvent;  
  13. };  
  14. //设置handlerEvent的值来动态装载事件响应函数  
  15. class Rectangle  
  16. {  
  17. private:  
  18.     std::string name;  
  19.     Sharp sharp;  
  20. public:  
  21.     void initial(void);  
  22.     const Sharp getSharp() const;  
  23.     <span style="color:#ff0000;">virtual</span> void onEvent(int param)  
  24.     {   
  25.         std::cout << "invode Rectangle's onEvent method,get parameter: " << param << std::endl;  
  26.     }  
  27. };  
  28. //Square类来继承Rectangle类,并重写onEvent  
  29. class Square : public Rectangle{  
  30. public:  
  31.     void onEvent(int param)  
  32.     {  
  33.         std::cout << "invode Square's onEvent method,get parameter: " << param << std::endl;  
  34.     }  
  35. };  
  36.   
  37. //类的实现方法  
  38. void Rectangle::initial()  
  39. {  
  40.     sharp.handlerEvent = std::bind(&Rectangle::onEvent,this,std::placeholders::_1);   
  41.     std::cout << "invode initial function!" << std::endl;  
  42. }  
  43. const Sharp Rectangle::getSharp() const  
  44. {  
  45.     return sharp;  
  46. }  
  47.   
  48. //测试函数  
  49. int main(int argc, char *argv[]){  
  50.     std::cout << "hi: " << std::setw(50) << "hello world!" << std::endl;  
  51.   
  52.     Rectangle rectangle;  
  53.     rectangle.initial();   
  54.     rectangle.getSharp().handlerEvent(23);    
  55.   
  56.     Square square;  
  57.     square.initial();  
  58.     square.getSharp().handlerEvent(33);  
  59.   
  60.     std::cin.get();  
  61. }  
  62. //输出结果  
  63. /*hi:                                       hello world! 
  64.     invode initial function! 
  65.     invode Rectangle's onEvent method,get parameter: 23 
  66.     invode initial function! 
  67.     invode Square's onEvent method,get parameter: 33*/  

总结:

1.typedef function<void(FrameworkPtr)> FrameworkFunc  这个定义代表FrameworkFunc是一个有一个FrameworkPtr为参数,无返回的函数。

2.“继承就像一条贼船,上去就下不来了”,而借助std::function和std::bind,大多数情况下,你都不用上贼船。

3 如果没有std::bind,那么std::function就什么都不是,而有了bind(),“同一个类的不同对象可以delegate给不同的实现,从而实现不同的行为”。

猜你喜欢

转载自blog.csdn.net/jisuanji198509/article/details/80711511