Cocos2dx 3.0 提高篇(十二) lambda表达式的使用

http://www.tuicool.com/articles/nIf2imU

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

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

bool compare(int & a, int & b)
{
    return a > b;   // 降序排序
}
然后,再这样调用: 
sort(a, a+n, compare);
然而,用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);
恩,就这样子吧。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值