在介绍3.0新的触摸机制之前,我们有必要先介绍一下3.0新引进的C++ 11的Lambda表达式。
首先,什么是Lambda表达式呢?
Lambda表达式是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的Lambda抽象,是一个匿名函数,即没有函数名的函数。相信有数学背景的孩子,现在是不是感觉到Lambda这个读音很耳熟呢?嘿嘿
基本语法如下:
[捕获列表](形参列表) mutable->返回值类型 复合语句
其中除了“[]”(其中捕获列表可以为空)和“复合语句”(相当于具名函数定义的函数体),其它都是可选的。它的类型是唯一的具有成员operator()的非联合的类类型,称为闭包类型(closure type)。
例如调用<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;});//不捕获时才可转换为函数指针Lambda表达式可以嵌套使用。
例如创建一个MenuItem,如果不使用Lambda,需要为这个item写一个回调函数,代码如下:
auto closeItem=MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
void HelloWorld::menuCloseCallback(Object* sender) { Director::getInstance()->end(); }
auto closeItem=MenuItemImage::create( "CloseNoraml.png", "CloseSeleceted.png", [](Object* pSender) { Director::getInstance()->end(); //直接在这边添加代码 });
auto callEnd=[](Object* pSender) { Director::getInstance()->end(); //这里直接添加代码 }; auto closeItem=MenuItemImage::create("CloseNormal.png","CloseSelected.png",callEnd);
如果要设定表达式能够访问外部变量,可以在[]内写入&或者=加上变量名,其中&表示按引用访问,=表示按值访问,变量之间用逗号分隔,比如[=number, &name]表示按值访问变量number,而按引用访问name。
用&引用来举个例子:假设点击按钮后,我要创建一个精灵。修改callEnd:
auto callEnd=[](Object* pSender) { auto sprite=Sprite::create("Hello.png"); sprite->setPosition(Point(50,50)); this->addChild(sprite,5); //这里会报错 }
auto callEnd=[&](Object* pSender) { auto sprite=Sprite::create("Hello.png"); sprite->setPosition(Point(50,50)); this->addChild(sprite,5); //正常运行 }