C++ 11 学习之 -- std::bind

5040阅读 0评论2016-06-18 sytpb
分类:C/C++

(一)C++ 11 std::bind 与原来的bind1st 2nd 有什么区别?

C++98中,有两个函数bind1st和bind2nd,它们分别可以用来绑定functor的第 一个和第二个参数,它们都是只可以绑定一个参数。各种限制,使得bind1st和bind2nd的可用性大大降低。


图中可以看到C++14更强大

std::bind就是废止了bind1st和bind2nd这二个函数配接器(effective C++ 40条)里这么翻译,一共有四个标准配接器(bind1st,bind2nd not1,not2)说实在这四个研究过半天,也用过,感觉就是半成品,好在C++11废了他们。

关于std::bind 看了不少资料,下面这位总结很好,有深度有例子,就不细说了,里面几点重要话我在下面提出来。
http://blog.csdn.net/elloop/article/details/50323113
【C++ STL学习与应用总结】22: 函数组合之1:如何使用std::bind (since C++11)

1:bind是函数组合概念
std::bind是STL实现函数组合概念的重要手段,std::bind可以绑定
普通函数(函数指针)、
lambda表达式、
成员函数、
成员变量、
模板函数、
嵌套std::bind等

2:bind返回值

bind返回一个基于fn的函数对象(function object), 其参数被绑定到args上.

fn的参数要么是绑定到值,要么是绑定到placeholders(占位符,如_1, _2, …, _N)

3:以下是使用std::bind的一些需要注意的地方:

4: std::bind 绑定类成员函数、成员变量

成员函数区别于普通函数的一个特殊之处在于,其第一个参数必须是该类型的一个对象(或对象的指针或引用),
如果成员函数有多个参数,参数是从bind的第二个参数开始,
std::bind(&成员函数,第一个参数,第二个参数,第三个参数..)


<<理解CC_CALLBACK_0, CC_CALLBACK_1, CC_CALLBACK_2, CC_CALLBACK_3>>
作者同上:elloophttp://blog.csdn.net/elloop/article/details/50445722

cocos2d中有这样的定义    

点击(此处)折叠或打开

  1. #define CC_CALLBACK_0(__selector__,__target__,...)std::bind(&__selector__,__target__,##__VA_ARGS__)
  2. #define CC_CALLBACK_1(__selector__,__target__,...)std::bind(&__selector__,__target__,std::placeholders::_1,##__VA_ARGS__)
  3. #define CC_CALLBACK_2(__selector__,__target__,...)std::bind(&__selector__,__target__,std::placeholders::_1,std::placeholders::_2,##__VA_ARGS__)
  4. #define CC_CALLBACK_3(__selector__,__target__,...)std::bind(&__selector__,__target__,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,##__VA_ARGS__)



(二) coscos2d 3.x 中的std::bind案例代码

CC_CALLBACK__1 _2 _3 代表成员函数参数个数


点击(此处)折叠或打开

  1. 点击(此处)折叠或打开
  2. bool RedSide::init()
  3. {
  4.     ...
  5.     EventListenerCustom*listener=EventListenerCustom::create("robot_attacking",CC_CALLBACK_1(RedSide::attackedByGreen,this));
  6.     Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(listener,1);
  7.     ...
  8. }
  9.      
  10. void RedSide::attackedByGreen(cocos2d::EventCustom*event)
  11. {
  12.     ......
  13. }


CC_CALLBACK_1 绑定成员 RedSide::attackedByGreen,用了一个占位符来锁定此函数需要一个参数

Create 函数定义


点击(此处)折叠或打开

  1. 点击(此处)折叠或打开
  2. EventListenerCustom*EventListenerCustom::create(conststd::string&eventName,conststd::function&callback)
  3. {
  4.         EventListenerCustom*ret=new(std::nothrow)EventListenerCustom();
  5.         if(ret&&ret->init(eventName,callback))
  6.         {
  7.             ret->autorelease();
  8.         }
  9.         else
  10.         {
  11.             CC_SAFE_DELETE(ret);

  12.         }
  13.         return ret;
  14. }


事件的触发

点击(此处)折叠或打开

  1. 点击(此处)折叠或打开
  2. EventCustom event("robot_attacking");
  3. Director::getInstance()->getEventDispatcher()->dispatchEvent(&event);

最终通过"robot_attacking"EventDispatcher 会找到此事件的listener,然后listener里保存着回调functor, functor 会被传递一个event参数,
进行回调就回到了成员函数这里。



-----------------------------------------------------------------------------------------------------------------------
Cocos2d 3.x 里有多种事件类型,每一种事件类型对就一种事件监听器,事件监听器保存着不同的回调函数。


点击(此处)折叠或打开

  1. 点击(此处)折叠或打开
  2. auto listener=EventListenerTouchOneByOne::create();//创建一个单点触摸事件:EventListenerTouchAllAtOnce 为多点
  3. auto listener1=EventListenerTouchOneByOne::create();
  4. //设置这些事件的的回调方法
  5. listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
  6. bool HelloWorld::onTouchBegan(Touch*touch,Event*event)
  7. {
  8. }






上一篇:C++ 局部类的作用 和 LevelDB 的一个应用场景
下一篇:C++ 11 学习之 -- std::bind总结