在Cocos2d-x中点击某个按钮要执行一个回调函数时,一般的写法是以下这样 :
// add a "share" icon to exit the progress. it‘s an autorelease object CCMenuItemImage *pShareItem = CCMenuItemImage::create( "share.png", "share.png", this, menu_selector(HelloWorld::menuShareCallback));
其中的HelloWorld::menuShareCallback是HelloWorld类的一个函数, 生命为 :
// a selector callback to share button void menuShareCallback(CCObject* pSender);
这个menuShareCallback就相当与Java中Listener的回调函数, 那么Cocos2d-x的selector机制是如何实现的呢 ?
要明白selector机制, 我们首先要清楚C/C++语言中的函数指针, 函数指针其实就是指向函数的指针。 在C/C++中, 函数会以内存地址来标识, 从函数的内存地址开始执行就相当于执行该函数。那么用什么来代表函数指针的地址呢, 其实C/C++语言中的函数名就代表了函数在内存中的地址。看下面的例子 :
#include <iostream>
// 定义一个函数指针类型, MethodPointer
typedef void (*MethodPointer)(int num);
// 普通函数
void printNum(int num)
{
cout << "The num is : " <<num<<endl;
}
int main(int argc, const char * argv[])
{
MethodPointer mp = printNum;
mp(444);
return 0;
}
在文件的上面我们定义了一个函数指针类型MethodPointer,和它对应的函数类型应该是没有返回值的,且有一个Int参数的函数, 例如上文中的void printNum(int num)函数, 在main中我们定义了一个MethodPointer指针,指向了printNum方法,然后执行mp(444);就相当于执行了printNum(444)方法。
对于C++来说还有一种是成员函数指针,它与C中的函数指针类似, 只是指针指向的是某个类中的成员函数。看下面这个例子 :
头文件
#ifndef __MenberCallback__MemberPointer__ #define __MenberCallback__MemberPointer__ class MemberPointer; // 定义一个成员函数指针 typedef void (MemberPointer::*MCallback)(int num); #include <iostream> class MemberPointer { public: MemberPointer(); ~MemberPointer(); void click(MCallback callback); void doSth(int code); } ; #endif /* defined(__MenberCallback__MemberPointer__) */
cpp
#include <iostream> #include "MemberPointer.h" using namespace std; MemberPointer::MemberPointer() { } MemberPointer::~MemberPointer() { } void MemberPointer::doSth(int code) { cout<<"call back method. "<<code<<endl; } void MemberPointer::click(MCallback callback) { // 执行回调, 因为在callback中传递的是自身的回调函数doStn,所以直接用this (this->*callback)(888); }
main函数 :
int main(int argc, const char * argv[]) { MemberPointer *mPointer = new MemberPointer(); mPointer->click(&MemberPointer::doSth) ; return 0; }
可见, 在click方法中我们执行了doSth方法, 打印出了888这几个数字。
参考资料 : http://zh.wikipedia.org/wiki/%E7%B1%BB%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88
最后看看Cocos2d-x中的selector的实现, 直接上代码,啥也不说了, 饿!!!!
头文件
// // MemberPointer.h // MenberCallback // // Created by mrsimple on 3/13/14. // Copyright (c) 2014 mrsimple. All rights reserved. // #ifndef __MenberCallback__MemberPointer__ #define __MenberCallback__MemberPointer__ #include <iostream> class MemberPointer; // 定义一个成员函数指针 typedef void (MemberPointer::*MCallback)(int num); // 定义selector #define callback_selector(_SEL) (MCallback)(&_SEL) class MemberPointer { public: MemberPointer(); ~MemberPointer(); void click(MCallback callback); void doSth(int code); void doSelector(int code); } ; #endif /* defined(__MenberCallback__MemberPointer__) */
cpp
// // MemberPointer.cpp // MenberCallback // // Created by mrsimple on 3/13/14. // Copyright (c) 2014 mrsimple. All rights reserved. // #include <iostream> #include "MemberPointer.h" using namespace std; MemberPointer::MemberPointer() { } MemberPointer::~MemberPointer() { } void MemberPointer::doSelector(int code) { cout<<"doSelector "<<code<<endl; } void MemberPointer::doSth(int code) { cout<<"call back method. "<<code<<endl; } void MemberPointer::click(MCallback callback) { // 执行回调, 因为在callback中传递的是自身的回调函数doStn,所以直接用this (this->*callback)(888); }
main
// // main.cpp // MenberCallback // // Created by mrsimple on 3/13/14. // Copyright (c) 2014 mrsimple. All rights reserved. // #include <iostream> #include "Selector.h" #include "MemberPointer.h" typedef void (*MP)(int stCode); void printNum(int num) { cout << "The num is : " <<num<<endl; } int main(int argc, const char * argv[]) { MemberPointer *mPointer = new MemberPointer(); mPointer->click(&MemberPointer::doSth) ; // selector的使用, 注意这里和上面的区别, callback_selector (XXXXXXXX) mPointer->click(callback_selector(MemberPointer::doSelector)) ; return 0; }
输出结果