Cocos2dx 3.0 过渡篇(十二) lambda表达式的使用

本篇博客来自star特530,转载请注明出处http://blog.csdn.net/start530/article/details/19913611

Cocos2dx 3.0 版本后加入了lambda表达式,或者说C++ 11终于引入了lambda表达式,那么,什么是lambda表达式呢?

例如调用<algorithm>中的std::sort,ISO C++ 98 的写法是要先写一个compare函数:

[cpp] view
plain
copy

  1. bool compare(int & a, int & b)  
  2. {  
  3.     return a > b;   // 降序排序  
  4. }  

然后,再这样调用:

[cpp] view
plain
copy

  1. sort(a, a+n, compare);  

然而,用ISO C++ 11 标准新增的Lambda表达式,可以这么写:

[cpp] view
plain
copy

  1. sort(a, a + n, [](int a, int b){return a > b;}); // 降序排序  

这样一来,代码是不是简洁多了呢?

由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:

[cpp] view
plain
copy

  1. auto f = [](int a, int b){return a > b;});  

和其它语言的一个较明显的区别是Lambda和C++的类型系统结合使用,如:

[cpp] view
plain
copy

  1. auto f = [=](int a, int b){return a > x;}); //x被捕获复制  
  2. int x = 0, y = 1;  
  3. auto g = [&](int x){return ++y;}); //y被捕获引用,调用g后会修改y,需要注意y的生存期  
  4. bool(*fp)(int, int) = [](int a, int b){return a > b;}); //不捕获时才可转换为函数指针  

------------------------------------------------------------------------

下面讲下在cocos2dx 3.0 应该如何使用lambda:

我先创建一个menu ,如果不使用labmda,menu里 item 需再写一个回调函数,如下:

[cpp] view
plain
copy

  1. auto closeItem = MenuItemImage::create(  
  2.                                         "CloseNormal.png",  
  3.                                         "CloseSelected.png",  
  4.                                         CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));  
  5.                                           
  6. void HelloWorld::menuCloseCallback(Object* sender)  
  7. {  
  8.     Director::getInstance()->end();  
  9. }  

使用了lambda后,可以这么使用:

[cpp] view
plain
copy

  1. auto closeItem = MenuItemImage::create(  
  2.                                         "CloseNormal.png",  
  3.                                         "CloseSelected.png",  
  4.                                         [](Object* sender)  
  5.                     {  
  6.                         Director::getInstance()->end();//直接在这里添加按钮要调用的代码  
  7.                     });  

这种写法是不是简洁很多?当然了,也可以将回调 的代码单独取出来,这种写法的好处是可以多出调用callEnd。如下:

[cpp] view
plain
copy

  1. auto callEnd = [](Object* sender)  
  2. {  
  3.     Director::getInstance()->end();//直接在这里添加按钮要调用的代码   
  4. };    
  5. auto closeItem = MenuItemImage::create(  
  6.                                         "CloseNormal.png",  
  7.                                         "CloseSelected.png",  
  8.                     allEnd);      

默认情况下,即捕获字段为 [] 时,lambda表达式是不能访问任何外部变量的,即表达式的函数体内无法访问当前作用域下的变量。
如果要设定表达式能够访问外部变量,可以在 [] 内写入 & 或者 = 加上变量名,其中 & 表示按引用访问,= 表示按值访问,变量之间用逗号分隔,比如 [=factor, &total] 表示按值访问变量 factor,而按引用访问 total。

用 & 引用来举个例子:假设点击按钮后,我要创建一个精灵。修改callEnd:

[cpp] view
plain
copy

  1. auto callEnd = [](Object* sender)  
  2. {  
  3.     auto sp = Sprite::create("Hello.png");  
  4.     sp->setPosition(Point(100,100));  
  5.     this->addChild(sp,10);//这里报错  
  6. };    

上面这种写法是错误的,因为表达式无法访问当前作用于的变量。下面继续改代码:

[cpp] view
plain
copy

  1. auto callEnd = [&](Object* sender)  
  2. {  
  3.     auto sp = Sprite::create("Hello.png");  
  4.     sp->setPosition(Point(100,100));  
  5.     this->addChild(sp,10);//perfect  
  6. };    

这样就没问题了。

上面的例子都只是简单的应用。在cocos2dx用到lambda 的地方还有很多,例如创建一个监听事件:


[cpp] view plaincopy

  1. // Make sprite1 touchable  
  2. auto sprite1 = Sprite::create();  
  3. auto listener1 = EventListenerTouchOneByOne::create();  
  4. listener1->setSwallowTouches(true);  
  5.   
  6. listener1->onTouchBegan = [](Touch* touch, Event* event){  
  7.     auto target = static_cast<Sprite*>(event->getCurrentTarget());  
  8.     return false;  
  9. };  
  10.   
  11. listener1->onTouchMoved = [](Touch* touch, Event* event){  
  12.     auto target = static_cast<Sprite*>(event->getCurrentTarget());  
  13.     target->setPosition(target->getPosition() + touch->getDelta());  
  14. };  
  15.   
  16. listener1->onTouchEnded = [=](Touch* touch, Event* event){  
  17.     auto target = static_cast<Sprite*>(event->getCurrentTarget());  
  18. };                    
  19.   
  20.  _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);                                 
  21.       

恩,就这样子吧。

本篇博客来自star特530,转载请注明出处http://blog.csdn.net/start530/article/details/19913611
时间: 2024-12-24 08:54:56

Cocos2dx 3.0 过渡篇(十二) lambda表达式的使用的相关文章

Cocos2dx 3.0 过渡篇(二) 事件回调

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/18216679 3.0 后的事件回调函数接口都不一样了,例如按钮的menu_selector(),update的 schedule_selector等,都已成明日黄花.而新的回调接口,则由四个CC_CALLBACK取代. 下面先举例一些不同的调用方法: 1.按钮:CC_CALLBACK1 [cpp] view plaincopy 2.0   Me

Cocos2dx 3.0 过渡篇(十三) action的用法从一个故事说起

本篇博客来自star特530,转载请注明出处.http://blog.csdn.net/start530/article/details/20153367-------------动作到底该怎么玩?说的也就是runAction这货了.如果你觉得本文还是在写像MoveTo,SacleTo这类动作的用法的话,那你就错了.那样不够厚道.当然了,像Sequence,Spawn这类的东西多少也是会涉及到一点的.那到底要写什么呢?我们的故事从这里开始. 首先我们创建俩精灵,就命名为boy 和 girl 吧.

Cocos2dx 3.0 过渡篇(四) 创建项目

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/18620001 前天参加同学的婚礼,喝酒喝得差点没把胃都给吐出来.昨天一天 请假在家里休养.今早原地满血复活,觉得有必要再写篇博客,告诉大家,我又回来啦. 话说应该写点什么内容呢?干脆写个在3.0Alpha1版本上创建项目的流程吧,就当做笔记. 在Cocos2dx 3.0 Beta版本创建项目的方式已经更改,由于我近阶段都是用Alpha1版本开发

Cocos2dx 3.0 过渡篇(十五)帧动画的存储播放

前两篇博文用恶搞的形式写了action的相关使用,这算是自己的一种尝试,也可以说是心情的发泄.本篇是action三板斧的最后一板,经过深思熟虑后,我决定就用正常人的方式写吧... 这次主要介绍动画的创建即存储,要实现的功能有:1.创建四组动画,并存放至Array中: 2.创建四个虚拟方向按钮,控制精灵移动与播放相应方向的动画: -------------------------------------------------------------------------------------

Cocos2dx 3.0 过渡篇(十)资源加载进度条Loading...

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/19420317 本来这篇博文是昨晚就要写的,可是因为今早要去参加考驾照相关的体检,而我最害怕的就是视力没能达到5.0,毕竟这阶段对着屏幕的时间过久. 所以呢,昨晚我几乎没碰电脑,没玩手机,早睡早起.体检顺利通过! 首先,我要说的是:这次我要写的主题是进度条. 额,等等,先收起你手里愤怒的西瓜刀.我也才知道TestCpp也有这个例子啊.不过Test

Cocos2dx 3.0 过渡篇(五) 随机数的获取

本来上午是要转载一篇看起来还不错的博客,被cocos2dx官方微博推荐过.谁知道早上打开链接时那篇博客已经转为私密了.早知道昨晚就应该复制一下内容,今天厚脸皮的来篇原创岂不妙哉.哈哈. 1.简单的随机数用法:CCRANDOM_0_1 示例如下: [cpp] view plaincopy int HelloWorld::getRand(int start,int end)   {    float i = CCRANDOM_0_1()*(end-start+1)+start;  //产生一个从st

Cocos2dx 3.0 过渡篇(三) 触摸机制

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/18325493 本来在中午休息时间打算大展拳脚,好好写一篇新触摸机制相关的博文,结果,等真正下手的时候才发现无从下手,很多地方自己都说不清,赶紧看了下testCpp,才发现原来是这样,还可以这样,哦?这样都行?哎,我还是太年轻了.   咱也只能挑简单的讲了. 假设要实现拖动一个精灵移动,那我们的步骤是: 1. 创建一个精灵sprite: 2.一个

Cocos2dx 3.0 过渡篇(九)浅谈容器Map

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/19284301 本篇接着上一篇的容器继续唠叨,了解上一篇:http://blog.csdn.net/start530/article/details/19170853 既然Vector是对比Array,那么Map就对比Dictionary吧.1.创建 [cpp] view plaincopy auto sp1 = Sprite::create("

Cocos2dx 3.0 过渡篇(十一) xml文档的读取与调用

尊重原创,转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/19632869 这阶段很忙,灰常忙,人又感冒了.前两天去报了驾校,所以下班回家后都在突击科目一,争取下周就去考.话说我们这边驾校报名费要六千,全国还有其他地方有这么高的吗? -------------------------------- 前天有人问我beta2 要如何读取xml文档,我刚要说用array的相关接口去读取,才想起beta之后早没有