cocos2dx中函式指標傳遞的方法
目的
看到群裡有個朋友搞了好幾天函式指標傳遞,沒搞好。所以寫一篇文章,旨在從cocos2dx中幫朋友們找到如何傳遞指標。
舊版本的函式指標傳遞
全域性函式函式指標呼叫
一般在C++11之前,我們一般是這樣定義一個函式指標型別。
[cpp] view plaincopyprint?- typede void(*pFunc)(int,...);
什麼意思呢?
[cpp] view plaincopyprint?- typedefvoid/*return type of function*/
- (*pFunc/*the pointer of function*/)
- (int,.../*the types of function parameters*/);
- typedefvoid/*函式返回型別*/(*pFunc/*函式指標*/)(int,.../*函式引數型別*/);
OK,那麼好了,該如何呼叫呢?
一般來說是像下面這樣的。
[cpp] view plaincopyprint?- typedefvoid(*pFunc)();
- void fA(){ };
-
void fB(pFunc pf){ (*pf)(
- void fC(){ fB(&fA);};
即為在fC中呼叫fB,fB的引數為fA指標。
成員函式函式指標的呼叫
那麼成員函式如何呼叫呢?
只需要加一個類名修飾符即可。
示例如下:
[cpp] view plaincopyprint?- class C;
- typedefvoid(C::*pFunc)();
- void C::fA(){};
- void C::fB(pFunc pf){ (this->*pf)()};
- void C::fC(){this->fB(&C::fA);};
其實,有心的朋友應該會注意到cocos2dx 版本中的各種selector即為巨集定義的函式指標的引用,定義如下:
- typedefvoid (Ref::*SEL_CallFunc)();
- typedefvoid (Ref::*SEL_CallFuncN)(Node*);
- typedefvoid (Ref::*SEL_CallFuncND)(Node*, void*);
- typedefvoid (Ref::*SEL_CallFuncO)(Ref*);
- typedefvoid (Ref::*SEL_MenuHandler)(Ref*);
- typedefvoid (Ref::*SEL_SCHEDULE)(float);
- #define callfunc_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR)
- #define callfuncN_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR)
- #define callfuncND_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR)
- #define callfuncO_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR)
- #define menu_selector(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR)
- #define schedule_selector(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)
所以不懂函式指標的朋友完全可以模仿它。 相信你很快就能上手。
C++11 中std::function的應用
cocos2dx 裡面std::function定義的各種回撥的解析
假設我們不知道std::function如何使用,那麼只有瀏覽cocos2dx3.X裡面的原始碼,我們會發現有大量的callBack 是用std::function定義的。
我們在此,首先用cocos2dx裡面的網路http請求的返回函式舉例。
HttpRequest 的回撥定義為
inline void setResponseCallback(const ccHttpRequestCallback& callback)
{
_pCallback = callback;
}
追蹤ccHttpRequestCallback,可以發現ccHttpRequestCallback即為std::function定義的:
typedef std::function<void(HttpClient* client, HttpResponse* response)> ccHttpRequestCallback;
使用過的同學應該知道怎麼呼叫的,
一般都是 setResponseCallback(CC_CALLBACK_2(ClassName::jsonRequestCompleted,this));
CC_CALLBACK是什麼東東,其實就是std::bind的引用巨集定義。我們檢視定義如下:
[cpp] view plaincopyprint?- #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
- #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
- #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
- #define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)
很明顯,CC_CALLBACK_2就是 std::bind裡面傳引數,第一個是引用引數表示函式,第二個是目標,第三個,第四個是佔位符,後面是不定引數。
所以可以等價代換為std::bind,那麼我們上面的回撥可以變成
setResponseCallback(std::bind(&ClassName::jsonRequestCompleted,this,std::placeholders::_1,std::placeholders::_2));
自定義std::function的應用
通過以上分析,相信大家已經掌握瞭如何通過std::function傳遞函式,以及std::bind去呼叫。不過為了照顧一些基礎薄弱的朋友,我還是給出一個簡單的例子。
[cpp] view plaincopyprint?- class C;
- void C::fA(){}
- void C::fB(const std::function<void()> &func)
- {
- if (func)
- {
- func();
- }
- }
- void C::fC()
- {
- fB(std::bind(&c::fA,this));
- }
關於非成員函式使用std::function
非成員函式使用std::function和上面的函式指標實際上是一致的,鑑於它比較容易,就不在此贅述了,還不會的朋友可以試一下。