Cocos2dx 3.X 中CC_CALLBACK_0 1 2 3理解

c++ 11 基础 :

    std::function

        类模版 std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标进行存储、复制、和调用操作,这些目标包括函数、lambda表达式、绑定表达式、以及其它函数对象等。

用法示例:

①保存自由函数

?
1
2
3
4
5
6
7
8
void  printA( int  a)
{
     cout<<a<<endl;
}
 
  std::function< void ( int  a)> func;
  func = printA;
  func(2);

运行输出: 2

②保存lambda表达式

?
1
2
std::function< void ()> func_1 = [](){cout<< "hello world" <<endl;};
     func_1();

运行输出:hello world

③保存成员函数

?
1
2
3
4
5
6
7
8
9
10
struct  Foo {
     Foo( int  num) : num_(num) {}
     void  print_add( int  i)  const  { cout << num_+i <<  '\n' ; }
     int  num_;
};
 
  // 保存成员函数
     std::function< void ( const  Foo&,  int )> f_add_display = &Foo::print_add;
     Foo foo(2);
     f_add_display(foo, 1);

    运行输出: 3

    bind        bind是一组用于函数绑定的模板。在对某个函数进行绑定时,可以指定部分参数或全部参数,也可以不指定任何参数,还可以调整各个参数间的顺序。对于未指定的参 数,可以使用占位符_1、_2、_3来表示。_1表示绑定后的函数的第1个参数,_2表示绑定后的函数的第2个参数,其他依次类推。

下面通过程序例子了解一下用法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
using  namespace  std;
class  A
{
public :
     void  fun_3( int  k, int  m)
     {
         cout<<k<< " " <<m<<endl;
     }
};
 
void  fun( int  x, int  y, int  z)
{
     cout<<x<< "  " <<y<< "  " <<z<<endl;
}
 
void  fun_2( int  &a, int  &b)
{
     a++;
     b++;
     cout<<a<< "  " <<b<<endl;
}
 
int  main( int  argc,  const  char  * argv[])
{
     auto  f1 = bind(fun,1,2,3);  //表示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
     f1();  //print:1  2  3
     
     auto  f2 = bind(fun, placeholders::_1,placeholders::_2,3);
     //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别有调用 f2 的第一,二个参数指定
     f2(1,2); //print:1  2  3
     
     auto  f3 = bind(fun,placeholders::_2,placeholders::_1,3);
     //表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别有调用 f3 的第二,一个参数指定
     //注意: f2  和  f3 的区别。
     f3(1,2); //print:2  1  3
     
     
     int  n = 2;
     int  m = 3;
     
     auto  f4 = bind(fun_2, n,placeholders::_1);
     f4(m);  //print:3  4
 
     cout<<m<<endl; //print:4  说明:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的
     cout<<n<<endl; //print:2  说明:bind对于预先绑定的函数参数是通过值传递的
     
     
     A a;
     auto  f5 = bind(&A::fun_3, a,placeholders::_1,placeholders::_2);
     f5(10,20); //print:10 20
     
     std::function< void ( int , int )> fc = std::bind(&A::fun_3, a,std::placeholders::_1,std::placeholders::_2);
     fc(10,20); //print:10 20
     
     return  0;
}

    CC_CALLBACK

        一、通过 HelloWorldScene 中的 closeItem 开始

在cocos2d-x 2.x 版本中:

?
1
2
3
4
5
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                         "CloseNormal.png" ,
                                         "CloseSelected.png" ,
                                         this ,
                                         menu_selector(HelloWorld::menuCloseCallback));

在cocos2d-x 3.0 版本中:

?
1
2
3
4
auto  closeItem = MenuItemImage::create(
                                            "CloseNormal.png" ,
                                            "CloseSelected.png" ,
                                            CC_CALLBACK_1(HelloWorld::menuCloseCallback,  this ));


?
1
2
3
4
5
6
7
8
void  HelloWorld::menuCloseCallback(Object* pSender)
{
     Director::getInstance()->end();
 
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     exit (0);
#endif
}

注意到在3.0版本中使用到 CC_CALLBACK_1 这样一个宏定义。

?
1
2
3
4
5
// 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_CALCC_CALLBACK_1(HelloWorld::menuCloseCallback,this)LBACK_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__)

这里主要注意两点:一是 std::bind,二是##_VA_ARGS_; ##_VA_ARGS_是可变参数宏

原来还有 CC_CALLBACK_0 1 2 3;而其中又有什么区别呢?

1、首先我们看看3.0版本中MenuItemImage的create方法:

?
1
MenuItemImage * MenuItemImage::create( const  std::string& normalImage,  const  std::string& selectedImage,  const  ccMenuCallback& callback)

其中的回调参数是 ccMenuCallback 

?
1
typedef  std::function< void (Object*)> ccMenuCallback

来这里使用到了 C++ 中的 function 语法。

注意到 在 CC_CALLBACK_  的宏定义的中使用到的是 C++ 的 bind 语法,怎么不一致了呢? -- 见下面第四点 function


2、看回 CC_CALLBACK_  的宏定义

原来 CC_CALLBACK_  的宏定义中后面的 0 1 2 3分别表示的是 不事先指定回调函数参数的个数。

例如说 CC_CALLBACK_ 1 表示的是,回调函数中不事先指定参数是一个,而事先指定的回调函数的参数 可以任意多个

而且要注意到其中 不指定回调函数参数  和  指定回调函数参数  的顺序,注意不事先指定的在前,事先指定的在后

下面通过例子说明这一点:

假设回调函数:

?
1
2
// a selector callback
     void  menuCloseCallback(Object* pSender, int  a, int  b);
?
1
2
3
4
5
6
7
8
9
void  HelloWorld::menuCloseCallback(Object* pSender, int  a, int  b)
{
     std::cout<<a<< "  " <<b<<std::endl;
     Director::getInstance()->end();
 
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     exit (0);
#endif
}

注意到在回调函数中输出 a b

?
1
2
3
4
auto  closeItem = MenuItemImage::create(
                                            "CloseNormal.png" ,
                                            "CloseSelected.png" ,
                                            CC_CALLBACK_1(HelloWorld::menuCloseCallback, this ,1,2));


注意中其中 指定了两个参数 1 2 

运行,在 点击closeItem  的时候,就会输出这两个事先指定的参数 1  2。

那么,不事先指定的参数是在什么时候传入的呢?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void  MenuItem::activate()
{
     if  (_enabled)
     {
         if ( _callback )
         {
             _callback( this );
         }
         
         if  (kScriptTypeNone != _scriptType)
         {
             BasicScriptData data( this );
             ScriptEvent scriptEvent(kMenuClickedEvent,&data);
             ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&scriptEvent);
         }
     }
}

    注意到其中的  _callback(this);  对了,这个时候就传入了 这个不事先指定的回调函数参数。

这样,closeItem 的回调函数的 void HelloWorld::menuCloseCallback(Object* pSender,int a,int b) 的三个参数都知道了。

第一个 不事先指定,在menu item调用 activate 的时候,_callback(this) 传入,this 也即是这个 menu item;第二、三个参数是事先指定的 1,2。


已经知道  CC_CALLBACK_  的宏定义是 std::bind 那么我们可以直接使用std::bind。

如下:

?
1
2
3
4
auto  closeItem = MenuItemImage::create(
                                            "CloseNormal.png" ,
                                            "CloseSelected.png" ,
                                            std::bind(&HelloWorld::menuCloseCallback,  this ,std::placeholders::_1,1,2));
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值