Chinaunix首页 | 论坛 | 博客
  • 博客访问: 290532
  • 博文数量: 63
  • 博客积分: 814
  • 博客等级: 军士长
  • 技术积分: 700
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-09 15:46
文章分类

全部博文(63)

文章存档

2017年(1)

2016年(4)

2015年(13)

2014年(9)

2012年(3)

2011年(33)

分类: C/C++

2016-06-18 09:12:03

(一)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的一些需要注意的地方:
  • bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的;
  • 对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
  • bind的返回值是可调用实体,可以直接赋给std::function对象;
  • 对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;
  • 类的this可以通过对象或者指针来绑定。

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. }






阅读(4883) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~