C++11中CC_CALLBACK_问题

本文是小编根据别人总结的,膜拜哪些牛人(汗!),毕竟我是菜鸟~呜呜

纵览源码

#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__)

 

1、  ##__VA_ARGS__及 # 、##   是什么?

       呵呵,我只知道 # 它是预处理符!

   (1.#

 假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化程字符串。例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing).
#incldue
#define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))
int main(void)
{
    int y =4;
    PSQR(y);
    PSQR(2+4);
    return 0;
}
输出结果:
the square of y is 16.
the square of 2+4 is 36.
第一次调用宏时使用“y”代替#x;第二次调用时用“2+4"代#x。

  (2.##

##运算符可以用于类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分。这个运算符把两个语言符号组合成单个语言符号。例如:
#define XNAME(n) x##n
这样宏调用:
XNAME(4)
展开后:
x4
程序:
#include
#define XNAME(n) x##n
#define PXN(n) printf("x"#n" = %d\n",x##n)
int main(void)
{
    int XNAME(1)=12;//int x1=12;
    PXN(1);//printf("x1 = %d\n", x1);
    return 0;
}
输出结果:
x1=12

   (3.可变参数宏 ...和_ _VA_ARGS_ _

__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。
实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所代表的字符串。比如:
#define PR(...) printf(__VA_ARGS__)
int main()
{
    int wt=1,sp=2;
    PR("hello\n");
    PR("weight = %d, shipping = %d",wt,sp);
    return 0;
}
输出结果:
hello
weight = 1, shipping = 2
省略号只能代替最后面的宏参数。
#define W(x,...,y)错误!

/***********************以上内容转自http://www.cnblogs.com/zhujudah/admin/EditPosts.aspx?opt=1*********************************************************************/



/*****************************下部分转自http://blog.csdn.net/star530/article/details/21245565************************************************/



首先看一段代码:

[cpp] view plain copy
  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.   
  6. girl_1 = Sprite::create("girl_1.png");//创建girl1  
  7. girl_1->setPosition(Point(visibleSize.width/3,visibleSize.height/2));  
  8. girl_1->setTag(10);  
  9. this->addChild(girl_1,1);  
  10.   
  11. girl_2 = Sprite::create("girl_3.png");//创建girl2  
  12. girl_2->setPosition(Point(2*visibleSize.width/3,visibleSize.height/2));  
  13. girl_2->setTag(20);  
  14. this->addChild(girl_2,1);  
  15.   
  16. //让boy运动,通过Callfunc回调到callback1  
  17. boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)),  
  18.                                     CallFunc::create(CC_CALLBACK_0(HelloWorld::callback1,this)),  
  19.                                     NULL));  
三个回调函数的实现:
[cpp] view plain copy
  1. void HelloWorld::callback1()  
  2. {  
  3.     CCLOG("in callback1");  
  4.     //girl1运动,最后回调到callback2  
  5.     girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,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,Point(0,200)),  
  13.         CallFunc::create(CC_CALLBACK_0(HelloWorld::callback3,this,girl_2,99)),  
  14.         NULL));  
  15.   
  16.     CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag());  
  17. }  
  18. void HelloWorld::callback3(Node* sender, long data)  
  19. {  
  20.     //最终输出  
  21.     CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data);  
  22.     CCLOG("girl2 dandan ask:what fake the CC_CALLBACK is?");  
  23. }  

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


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

[cpp] view plain copy
  1. // new callbacks based on C++11  
  2. #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)  
  3. #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)  
  4. #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)  
  5. #define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, 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
  1. int callback(int one,char two,double three);  
下面我们用bind来调用callback
[cpp] view plain copy
  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
  1. //让boy运动,通过Callfunc回调到callback1  
  2. boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)),  
  3.                                     CallFunc::create(std::bind(&HelloWorld::callback1,this)),  
  4.                                     NULL));  
[cpp] view plain copy
  1. void HelloWorld::callback1()  
  2. {  
  3.     CCLOG("in callback1");  
  4.     //girl1运动,最后回调到callback2  
  5.     girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,150)),  
  6.                                             CallFunc::create(std::bind(&HelloWorld::callback2,this,girl_1)),  
  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,Point(0,200)),  
  14.         CallFunc::create(std::bind(&HelloWorld::callback3,this,girl_1,99)),  
  15.         NULL));  
  16.   
  17.     CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag());  
  18.     CCLOG("girl_1 ask girl_2:I love girl_2");  
  19. }  
  20. void HelloWorld::callback3(Node* sender, long data)  
  21. {  
  22.     //最终输出  
  23.     CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data);  
  24.     CCLOG("girl2 dandan say:I know how to use CC_CALLBACK!");  
  25. }     
C++11中CC_CALLBACK_问题_第1张图片

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


你可能感兴趣的:(Cocos2D-x开发)