1. 程式人生 > >cocos2dx中函式指標傳遞的方法

cocos2dx中函式指標傳遞的方法

目的

看到群裡有個朋友搞了好幾天函式指標傳遞,沒搞好。所以寫一篇文章,旨在從cocos2dx中幫朋友們找到如何傳遞指標。

舊版本的函式指標傳遞

全域性函式函式指標呼叫

一般在C++11之前,我們一般是這樣定義一個函式指標型別。

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. typede void(*pFunc)(int,...);  

什麼意思呢?

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. typedefvoid/*return type of function*/
[cpp] view plaincopyprint
?在CODE上檢視程式碼片派生到我的程式碼片
  1. (*pFunc/*the pointer of function*/)  
[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. (int,.../*the types of function parameters*/);  
  2. typedefvoid/*函式返回型別*/(*pFunc/*函式指標*/)(int,.../*函式引數型別*/);  

OK,那麼好了,該如何呼叫呢?

一般來說是像下面這樣的。

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. typedefvoid(*pFunc)();  
  2. void fA(){ };  
  3. void fB(pFunc pf){ (*pf)(
    /*裡面加函式引數*/) };  
  4. void fC(){  fB(&fA);};  

即為在fC中呼叫fB,fB的引數為fA指標。

成員函式函式指標的呼叫

那麼成員函式如何呼叫呢?

只需要加一個類名修飾符即可。

示例如下:

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. class C;  
  2. typedefvoid(C::*pFunc)();  
  3. void C::fA(){};  
  4. void C::fB(pFunc pf){ (this->*pf)()};  
  5. void C::fC(){this->fB(&C::fA);};  

其實,有心的朋友應該會注意到cocos2dx 版本中的各種selector即為巨集定義的函式指標的引用,定義如下:

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. typedefvoid (Ref::*SEL_CallFunc)();  
  2. typedefvoid (Ref::*SEL_CallFuncN)(Node*);  
  3. typedefvoid (Ref::*SEL_CallFuncND)(Node*, void*);  
  4. typedefvoid (Ref::*SEL_CallFuncO)(Ref*);  
  5. typedefvoid (Ref::*SEL_MenuHandler)(Ref*);  
  6. typedefvoid (Ref::*SEL_SCHEDULE)(float);  
  7. #define callfunc_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR)
  8. #define callfuncN_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR)
  9. #define callfuncND_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR)
  10. #define callfuncO_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR)
  11. #define menu_selector(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR)
  12. #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?在CODE上檢視程式碼片派生到我的程式碼片
  1. #define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)
  2. #define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
  3. #define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)
  4. #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?在CODE上檢視程式碼片派生到我的程式碼片
  1. class C;  
  2. void C::fA(){}  
  3. void C::fB(const std::function<void()> &func)  
  4. {  
  5.     if (func)  
  6.     {  
  7.         func();  
  8.     }  
  9. }  
  10. void C::fC()  
  11. {  
  12.   fB(std::bind(&c::fA,this));  
  13. }  


關於非成員函式使用std::function

非成員函式使用std::function和上面的函式指標實際上是一致的,鑑於它比較容易,就不在此贅述了,還不會的朋友可以試一下。

申明: