Cocos2dx 3.x std::bind CC_CALLBACK_* 回調函數

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::bindspa

二是##_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方式也行,除了第一個位置的函數名稱,第二個位置調用該函數的對象,剩下的傳入的個數對應着回調函數中該有的參數個數。

相關文章
相關標籤/搜索