点击打开链接

本篇的主题就是揭露CC_CALLBACK 与 std::bind之间不可告人的秘密......

首先看一段代码:

[cpp] view plain copy print ?
  1. //先是创建3个精灵
  2. boy = Sprite::create("boy.png");//创建boy
  3. boy->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
  4. this->addChild(boy,1);
  5. girl_1 = Sprite::create("girl_1.png");//创建girl1
  6. girl_1->setPosition(Point(visibleSize.width/3,visibleSize.height/2));
  7. girl_1->setTag(10);
  8. this->addChild(girl_1,1);
  9. girl_2 = Sprite::create("girl_3.png");//创建girl2
  10. girl_2->setPosition(Point(2*visibleSize.width/3,visibleSize.height/2));
  11. girl_2->setTag(20);
  12. this->addChild(girl_2,1);
  13. //让boy运动,通过Callfunc回调到callback1
  14. boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)),
  15. CallFunc::create(CC_CALLBACK_0(HelloWorld::callback1,this)),
  16. NULL));

三个回调函数的实现:

[cpp] view plain copy print ?
  1. void HelloWorld::callback1()
  2. {
  3. cclOG("in callback1");
  4. //girl1运动,最后回调到callback2
  5. girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,150)),
  6. CallFunc::create(CC_CALLBACK_0(HelloWorld::callback2,this,girl_1)),
  7. NULL));
  8. }
  9. void HelloWorld::callback2(Node* sender)
  10. {
  11. //girl2运动,最后回调到callback3
  12. girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,200)),
  13. CallFunc::create(CC_CALLBACK_0(HelloWorld::callback3,girl_2,99)),
  14. NULL));
  15. cclOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag());
  16. }
  17. void HelloWorld::callback3(Node* sender,long data)
  18. {
  19. //最终输出
  20. cclOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data);
  21. cclOG("girl2 dandan ask:what fake the CC_CALLBACK is?");
  22. }

整个过程就是boy“勾引”girl1,但girl1显然对异性兴趣不大,于是她也勾引girl2......可是,girl2对同性异性都没兴趣,她只是淡淡的说了句:CC_CALLBACK到底是什么?调试如图:


好吧,先让我回口血,然后再来回答girl2的问题:CC_CALLBACK到底是什么碗糕(小编)?
我们先进CC_CALLBACK源码里看看:

[cpp] view plain copy print ?
  1. // new callbacks based on C++11
  2. #define CC_CALLBACK_0(__selector__,__target__,...) std::bind(&__selector__,##__VA_ARGS__)
  3. #define CC_CALLBACK_1(__selector__,std::placeholders::_1,##__VA_ARGS__)
  4. #define CC_CALLBACK_2(__selector__,std::placeholders::_2,##__VA_ARGS__)
  5. #define CC_CALLBACK_3(__selector__,std::placeholders::_3 ##__VA_ARGS__)

看完后恍然大悟!不看不知道,一看...和没看一样...
这里主要注意两点:一是 std::bind,二是##_VA_ARGS_; ##_VA_ARGS_是可变参数宏
,我就不多说了。重点讲的是std::bind。
std::bind是在C++ 11里新加入的成员。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表.
调用bind的一般形式为:
auto newCallback = bind(callback,arg_list);
其中,newCallback是一个可调用对象,arg_list是可以用逗号分隔的参数列表,至于是啥参数,那就看callback函数里有啥参数啦。也就是说,当我们调用newCallback时,newCallback会调用函数callback,并传递参数arg_list给callback.

看完上面的内容你的理解可能还比较模糊,那直接来个例子:有一个函数callback,如下,

[cpp] view plain copy print ?
  1. int callback(int one,char two,double three);

下面我们用bind来调用callback

[cpp] view plain copy print ?
  1. auto newCallback = bind(callback,_1,_2,1.5);
  2. int x = newCallback(10,'h'); //这句相当于:int x = callback(10,'h',1.5);

“_1″是一个占位符对象,用于表示当函数callback通过函数newCallback进行调用时,函数newCallback的第一个参数在函数callback的参数列表中的位置。第一个参数称为”_1″,第二个参数为”_2″,依此类推,有意思吧。至于‘1.5’是指默认参数,它处于_1和_2的后面,所以它就是double类型的参数了.
在强调一点就是:_1这类占位符都定义在一个名为placeholders的命名空间中,而这个命名空间本身定义在std的命名空间中。为了使用这些名字,两个命名空间都要写上,
如:

std::placeholders::_1;

这样编写贼麻烦,所以在要使用_1时,可以加上这么一句:
using namespace namespace_name; 恩,ok

恩,bind就介绍到这,讲的比较浅,不理解的可以百度研究下。最后再回过头来看下CC_CALLBACK的定义,是不是清晰多了?
最后在举个例子吧,还是之前的boy,girl1,girl2,只是他们之间传递“爱意”的方式要换下了。不用CC_CALLBACK,改用std::bind。代码如下 :

[cpp] view plain copy print ?
  1. //让boy运动,通过Callfunc回调到callback1
  2. boy->runAction(CCSequence::create(MoveBy::create(1.0f,
  3. CallFunc::create(std::bind(&HelloWorld::callback1,
  4. NULL));
[cpp] view plain copy print ?
  1. void HelloWorld::callback1()
  2. {
  3. cclOG("in callback1");
  4. //girl1运动,最后回调到callback2
  5. girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,
  6. CallFunc::create(std::bind(&HelloWorld::callback2,
  7. NULL));
  8. cclOG("boy ask girl_1:can you do my girlFriends?");
  9. }
  10. void HelloWorld::callback2(Node* sender)
  11. {
  12. //girl2运动,最后回调到callback3
  13. girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,
  14. CallFunc::create(std::bind(&HelloWorld::callback3,girl_1,
  15. NULL));
  16. cclOG("in callback2,(Sprite*)sender->getTag());
  17. cclOG("girl_1 ask girl_2:I love girl_2");
  18. }
  19. void HelloWorld::callback3(Node* sender,data);
  20. cclOG("girl2 dandan say:I kNow how to use CC_CALLBACK!");
  21. }



恩,就是这样子了。bind与CC_CALLBACK之间的关系就是这么的...简单。


尊重原创,转载请注定来自star特530:http://blog.csdn.net/start530/article/details/21245565

Cocos2dx 3.0 过渡篇十七 std::bind与CC_CALLBACK不得不说的故事的更多相关文章

  1. xcode – 在sprite中替换图像 – cocos2d游戏开发的iphone

    我想改变精灵图像.比方说这里,Sprite已经添加到图层.我有mainsprite(指针)可以访问它.如果我改变它工作完美.但是在这里我想改变sprite图像而不是不透明度.但不知道怎么样?提前感谢帮助我.萨加尔解决方法@sagar:在cocos2d0.99.x我用有用.下一个问题是,我如何回到我以前的精灵?

  2. Rxswift observable bind(to :) vs subscribe(onNext :)

    抱歉.我很困惑Rxswift中的绑定是什么.据我所知,除非观察者订阅了它,否则observable不会产生价值,例如myObservable.subscribe(onNext:{}).但是,当我阅读以下代码行时:我很困惑,为什么在不调用subscribe方法的情况下能够观察到isValidObservable?为什么我们可以在LoginViewController.swift中调用bind(to:

  3. 你怎么知道节点是否在屏幕spritekit swift上

    我试图弄清楚如何确定节点是在屏幕上还是在屏幕上可见.这只是节点的真/假属性吗?谢谢.您可以使用以下内容来测试节点是否在场景中:这假设self是SKScene的子类,例如GameScene.

  4. Android中的外部存储上的SQLite性能不佳

    我可以在我的真实应用程序中添加我已禁用locking并且它没什么区别.解决方法CommonsWare的评论是正确的.对数据库性能产生重大影响的是使用事务.在事务中包装插入循环.我不是100%确定它是否适用于InsertHelper,但您可以尝试用以下方法替换for循环:

  5. android – butterknife中bind和injectView之间的区别

    我正在使用butterknife库.我不太了解如何使用它.我发现injectView和bind做同样的事情,但我不太确定.任何人都可以解释这两者之间的区别.解决方法谁能解释这两者之间的区别?

  6. Android服务有关bind/unbind的问题?

    客户端可以使用bindService()/unbindService()调用原始的bind/unbind服务.我的问题是如何解析服务端的服务,而不是客户端调用unbindService(),可能我应该称之为unbindClient.我认为服务应该知道哪些客户端绑定了它,那么有没有办法告诉服务取消绑定特定客户端?

  7. 深入理解JS中的Function.prototype.bind()方法

    bind 是 ES5 中新增的一个方法,可以改变函数内部的this指向。这篇文章小编将带领大家深入理解Javascript中的Function.prototype.bind()方法。有需要的朋友们可以参考借鉴,下面来一起看看吧。

  8. JavaScript函数之call、apply以及bind方法案例详解

    这篇文章主要介绍了JavaScript函数之call、apply以及bind方法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  9. jquery绑定事件 bind和on的用法与区别分析

    这篇文章主要介绍了jquery绑定事件 bind和on的用法与区别,结合实例形式分析了jquery绑定事件 bind和on的基本功能、用法、区别与操作注意事项,需要的朋友可以参考下

  10. JS前端面试题详解之手写bind

    这篇文章主要为大家介绍了JavaScript前端面试题中常出现的问题:如何用JavaScript来实现内置的bind方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部