□文/传智播客C/C++高级讲师 童泽宇
个人简介:
曾就职于知名杀毒软件公司,长期从事计算机病毒研究,参与反病毒引擎、病毒鉴定器开发,熟悉CPU虚拟化技术,专注于操作系统底层,精通x86/x64平台逆向、C/C++,对Flame、sality、Conficker等知名病毒进行全面过分析,曾参与国安局相关项目的逆向分析,另外对Android系统的架构设计和实现原理有非常深入的理解和认识。童老师擅长将高深的知识通俗化,负责的理论简单化,热爱技术、热爱分享,在教学中将会把掌握最扎实最深入的技术积累献给每一位学员。
大家都应该知道,Cocos2dx在2.x的版本和1.x的版本一直延续着Objective-C的设计模式,这让很多C++程序员感觉很不适应。因为语法改的既不像OC也不像C++,所以在开发难度上来说还是比较大的,然而在这点对于OC的程序员来说,就有便宜可占了。因为1.x和2.x中都用到了OC的设计模式,这样他们上手起来是比较easy的。但3.0版本以后,cocos2dx的官方也感觉这样不是很好,所以3.0版本以后对cocos2dx引擎进行了一个重构工作,剔除了Objective-C的设计模式,增添了C++11的新特性。
下面,一起跟随我的文章深入探讨下我们Cocos2dx 正式版中的C++11的新特性吧!
特性1:lambda表达式
Cocos2dx 3.0版本后加入了lambda表达式,或者说C++11终于引入了lambda表达式,那么,什么是lambda表达式呢?
例如调用<algorithm>中的std::sort,ISO C++98的写法是要先写一个compare函数:
- bool compare(int & a, int & b)
- {
- return a > b; // 降序排序
- }
复制代码
然后,再这样调用:
然而,用ISO C++11标准新增的Lambda表达式,可以这么写:
- sort(a, a + n, [](int a, int b){return a > b;}); // 降序排序
复制代码
这样一来,代码是不是简洁多了呢?
由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:
- auto f = [](int a, int b){return a > b;});
复制代码
和其它语言的一个较明显的区别是Lambda和C++的类型系统结合使用,如:
- auto f = [=](int a, int b){return a > x;}); //x被捕获复制
- int x = 0, y = 1;
- auto g = [&](int x){return ++y;}); //y被捕获引用,调用g后会修改y,需要注意y的生存期
- bool(*fp)(int, int) = [](int a, int b){return a > b;}); //不捕获时才可转换为函数指针
复制代码
下面讲下在cocos2dx 3.0 应该如何使用lambda:
我先创建一个menu ,如果不使用labmda,menu里item需再写一个回调函数,如下:
- auto closeItem = MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
-
- void HelloWorld::menuCloseCallback(Object* sender)
- {
- Director::getInstance()->end();
- }
复制代码
使用了lambda后,可以这么使用:
- auto closeItem = MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- [](Object* sender)
- {
- Director::getInstance()->end();//直接在这里添加按钮要调用的代码
- });
复制代码
这种写法是不是简洁很多?当然了,也可以将回调的代码单独取出来,这种写法的好处是可以多处调用callEnd。如下:
- auto callEnd = [](Object* sender)
- {
- Director::getInstance()->end();//直接在这里添加按钮要调用的代码
- };
- auto closeItem = MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- allEnd);
复制代码
默认情况下,即捕获字段为[] 时,lambda表达式是不能访问任何外部变量的,即表达式的函数体内无法访问当前作用域下的变量。
如果要设定表达式能够访问外部变量,可以在[]内写入“&”或者“=”加上变量名,其中“&”表示按引用访问,“=”表示按值访问,变量之间用逗号分隔,比如[=factor, &total] 表示按值访问变量factor,而按引用访问total。
用“&”引用来举个例子:假设点击按钮后,我要创建一个精灵。修改callEnd:
- auto callEnd = [](Object* sender)
- {
- auto sp = Sprite::create("Hello.png");
- sp->setPosition(Point(100,100));
- this->addChild(sp,10);//这里报错
- };
复制代码
上面这种写法是错误的,因为表达式无法访问当前作用于的变量。下面继续改代码:
- auto callEnd = [&](Object* sender)
- {
- auto sp = Sprite::create("Hello.png");
- sp->setPosition(Point(100,100));
- this->addChild(sp,10);//perfect
- };
复制代码
这样就没问题了。
上面的例子都只是简单的应用。在cocos2dx用到lambda 的地方还有很多,例如创建一个监听事件:
- // Make sprite1 touchable
- auto sprite1 = Sprite::create();
- auto listener1 = EventListenerTouchOneByOne::create();
- listener1->setSwallowTouches(true);
-
- listener1->onTouchBegan = [](Touch* touch, Event* event){
- auto target = static_cast<Sprite*>(event->getCurrentTarget());
- return false;
- };
-
- listener1->onTouchMoved = [](Touch* touch, Event* event){
- auto target = static_cast<Sprite*>(event->getCurrentTarget());
- target->setPosition(target->getPosition() + touch->getDelta());
- };
-
- listener1->onTouchEnded = [=](Touch* touch, Event* event){
- auto target = static_cast<Sprite*>(event->getCurrentTarget());
- };
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1);
复制代码
Ok,那么我们特性其一的lambda就介绍完了。
特性2:auto关键字:
C++11中引入auto第一种作用是为了自动类型推导。
auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作。
auto实际上是在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响。
另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
cocos2dx 3.0使用了auto自动类型变量,这个是C++11的新标准,比如原来要指定变量是int还是float,现在可以用auto,在赋值的时候,编译器自动识别类型。
那么我们来举个简单的例子看一下,auto在cocos2dx中的应用:
现在是2.x的版本:
- CCSprite *pSprite = CCSprite::create(“HelloWorld.png”);
复制代码
3.0正式版以后:
- auto pSprite = Sprite::create(“HelloWorld.png”);
复制代码
是不是感觉很简单了?
好了C++11的新特性还有很多,我们在以后的日子中会陆续提到,好了,今天就到这里。
更多IT前沿、技术学习、面试技巧、IT笑话,微信搜索“CZTEKAN”,关注传智特刊,我为IT狂!或者点击进行邮件订阅
,了解传智特刊的最新资讯。
----------------------------------------------------------------------------------------------------
传智播客教育科技有限公司——专注于Java、.Net、PHP、网页平面UI、iOS、C/C++设计工程师的培训