boy = Sprite::create("boy.png")//建立boy boy->setPosition(Point(visibleSize.width/2, visibleSize.height/2)); this->addChild(boy,1); girl_1 = Sprite::create("girl1.png");//建立girl_1 girl_1->setPosition(Point(visibleSize.width/3,visibleSize.height/2)); girl_1->setTag(10); this->addChild(girl_1,1); gitl_2 = Sprite::create("girl2.png")//建立girl_2 gitl_2->setPosition(Point(2*visibleSize.width/3,visibleSize.height/2)); girl_2->setTag(20); this->addChild(girl_2,1); //让boy运动,经过Callfunc回调到callback1 boy->runAction(CCSequence::create(MoveBy::create(1.0f,Poin(0,100)), CallFunc::create(CC_CALLBACK_0(HelloWorld::callback1,this)),NULL));
对应三个回调函数的实现:git
void HelloWorld::callback1() { CCLOG("in callback1"); //girl1运动,最后回调到callback2 girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,150)), CallFunc::create(CC_CALLBACK_0(HelloWorld::callback2,this,girl_1)),NULL)); } void HelloWorld::callback2(Node* sender) { //girl2运动,最后回调到callback3 girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,200)), CallFunc::create(CC_CALLBACK_0(HelloWorld::callback3,this,girl_2,99)),NULL)); CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag()); } void HelloWorld::callback3(Node* sender, long data) { //最终输出 CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld" ,(Sprite*)sender->getTag(),data); CCLOG("girl2 dandan ask:what fake the CC_CALLBACK is?"); }
调试输出结果:web
查看CC_CALLBACK_*,回调函数源码:函数
// new callbacks based on C++11 #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__) #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__) #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__) #define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__),
这里须要注意两点:this
一是 std::bind,spa
二是##_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,以下,code
int callback(int one,char two,double three);
下面咱们用bind来调用callbackorm
auto newCallback = bind(callback,_1,_2,1.5); 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;three
这样编写贼麻烦,因此在要使用_1时,能够加上这么一句:
using namespace namespace_name; 恩,ok
恩,bind就介绍到这,讲的比较浅,不理解的能够百度研究下。最后再回过头来看下CC_CALLBACK的定义,是否是清晰多了?
最后在举个例子吧,仍是以前的boy,girl1,girl2,只是他们之间传递“爱意”的方式要换下了。不用CC_CALLBACK,改用std::bind。代码以下 :
//让boy运动,经过Callfunc回调到callback1 boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)), CallFunc::create(std::bind(&HelloWorld::callback1,this)), NULL));
void HelloWorld::callback1() { CCLOG("in callback1"); //girl1运动,最后回调到callback2 girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,150)), CallFunc::create(std::bind(&HelloWorld::callback2,this,girl_1)),NULL)); CCLOG("boy ask girl_1:can you do my girlFriends?"); } void HelloWorld::callback2(Node* sender) { //girl2运动,最后回调到callback3 girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,200)), CallFunc::create(std::bind(&HelloWorld::callback3,this,girl_1,99)),NULL)); CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag()); CCLOG("girl_1 ask girl_2:I love girl_2"); } void HelloWorld::callback3(Node* sender, long data) { //最终输出 CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data); CCLOG("girl2 dandan say:I know how to use CC_CALLBACK!"); }
调试结果输出:
我的理解:
其实使用哪个CC_CALLBACK_*回调函数都能实现对应的回调功能,当时直接使用std::bind方式也行,除了第一个位置的函数名称,第二个位置调用该函数的对象,剩下的传入的个数对应着回调函数中该有的参数个数。