Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}注意到在回调函数中输出 a b
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback,this,1,2));注意中其中 指定了两个参数 1 2
运行,在 点击closeItem 的时候,就会输出这两个事先指定的参数 1 2。
那么,不事先指定的参数是在什么时候传入的呢?
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。
3、bind
已经知道 CC_CALLBACK_ 的宏定义是 std::bind 那么我们可以直接使用std::bind。
如下:
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
std::bind(&HelloWorld::menuCloseCallback, this,std::placeholders::_1,1,2));
4、function
最后就解决上面的一个疑惑。
std::function func = std::bind(&HelloWorld::menuCloseCallback,this, std::placeholders::_1,1,2);
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
func);
5、使用lambda表达式
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
[&](Object *sender){
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
});可见使用lambda表达式可以极大的简化代码程序,不需要再定义一个回调函数,直接将在回调中的操作在闭包中体现即可。
二、在cocos2d-x中,还有一个地方是需要大量使用到回调函数的,这就是回调动作:CCCallFunc、CCCallFuncN、CCCallFuncND、CCCallFuncO。
但是这四个回调动作在 3.0 版本中已经都提示 deprecate 了。那么在3.0 版本中已经只剩下 CallFunc 和 CallFuncN.
下面是官方文档中的说明:
CallFunc
can be created with
an std::function
CallFuncN
can be created with
an std::function
CallFuncND
and CallFuncO
were
removed since it can be created with simulated with CallFuncN
and CallFunc
.
See ActionsTest.cpp for more examples
其中:CallFuncND 和 CallFuncO 都可以通过 CallFunc 和 CallFuncN 进行实现。下面通过例子详细的介绍这两个回调动作的用法。
1、CallFunc
static CallFunc * create(const std::function& func);关于CallFunc的例子,在文档中已经有体现:
// in v2.1
CCCallFunc *action1 = CCCallFunc::create( this, callfunc_selector( MyClass::callback_0 ) );
// in v3.0 (short version)
auto action1 = CallFunc::create( CC_CALLBACK_0(MyClass::callback_0,this));
auto action2 = CallFunc::create( CC_CALLBACK_0(MyClass::callback_1,this, additional_parameters));
// in v3.0 (long version)
auto action1 = CallFunc::create( std::bind( &MyClass::callback_0, this));
auto action2 = CallFunc::create( std::bind( &MyClass::callback_1, this, additional_parameters));
// in v3.0 you can also use lambdas or any other "Function" object
auto action1 = CallFunc::create(
[&](){
auto s = Director::sharedDirector()->getWinSize();
auto label = LabelTTF::create("called:lambda callback", "Marker Felt", 16);
label->setPosition(ccp( s.width/4*1,s.height/2-40));
this->addChild(label);
} );
2、CallFuncN
static CallFuncN * create(const std::function& func);注意到该回调动作带有一个Node*参数。
假设回调函数:
void ActionCallFuncN::callback(Node* sender )
auto action = Sequence::create(
MoveBy::create(2.0f, Point(150,0)),
CallFuncN::create( CC_CALLBACK_1(ActionCallFuncN::callback, this)),
NULL);
auto action = Sequence::create(
MoveBy::create(2.0f, Point(150,0)),
CallFuncN::create(std::bind(&ActionCallFuncN::callback,this,std::placeholders::_1)),
NULL);
auto action = Sequence::create(
MoveBy::create(2.0f, Point(150,0)),
CallFuncN::create([&](Node* sender){
//回调动作代码
}),
NULL);
受益于C++11的新语法特性 std::bind ; CallFuncND 和 CallFuncO 都可以通过 CallFunc 和 CallFuncN 进行实现
3、CallFuncND :回调动作中带有一个Node*参数和一个void*参数
实现过程类似于 CallFuncN
假设回调函数是 :void ActionCallFuncND::doRemoveFromParentAndCleanup(Node* sender,
bool cleanup)
那么在回调动作中:
CallFuncN::create( CC_CALLBACK_1(ActionCallFuncND::doRemoveFromParentAndCleanup,
this, true))
这样就实现了等价于 CallFuncND
的回调动作。
4、CallFuncO :回调动作中带有一个Object*参数
实现过程类似于 CallFunc
假设回调函数是: void ActionCallFuncO::callback(Node* node, bool cleanup)
那么在回调动作中:
CallFunc::create( CC_CALLBACK_0(ActionCallFuncO::callback, this, _grossini,
true)
这样就实现了等价于 CallFuncO 的回调动作。
三、总结
在新版的回调处理中,采用了C++11中的 std::function 、std::bind 、lambda 表达式,使得回调的处理变得形式多样,代码灵活了,而其中的lambda表达式可以极大的简化回调代码,推荐使用。