SEL_CallFuncN,SEL_CallFuncO等的區別


ocos2d-x中有大量的回調函數的應用,主要有以下幾類,看下CCObject.h中的定義

typedef void (CCObject::*SEL_SCHEDULE)(float);// 用來調update
typedef void (CCObject::*SEL_CallFunc)();// 用來自定義無參回調
[cpp]  view plain copy
  1. typedef void (CCObject::*SEL_CallFuncN)(CCNode*);// 帶執行者回調  
  2. typedef void (CCObject::*SEL_CallFuncND)(CCNode*, void*); // 帶一個自定參數的回調  
  3. typedef void (CCObject::*SEL_CallFuncO)(CCObject*);  
  4. typedef void (CCObject::*SEL_MenuHandler)(CCObject*);  
  5. typedef void (CCObject::*SEL_EventHandler)(CCEvent*);  
  6. typedef int (CCObject::*SEL_Compare)(CCObject*);  
  7.   
  8. #define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)  
  9. #define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)  
  10. #define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)  
  11. #define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)  
  12. #define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)  
  13. #define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)  
  14. #define event_selector(_SELECTOR) (SEL_EventHandler)(&_SELECTOR)  
  15. #define compare_selector(_SELECTOR) (SEL_Compare)(&_SELECTOR)  

本質上,就是函數指針的應用。

 

但是,我們知道,在C中,函數指針是很普遍的應用。一般函數的函數名就是指針,不過是常量,再定義一個函數指針就是一個變量,這個變量可以指向這一類函數的地址。

比如:

 

[cpp]  view plain copy
  1. typedef void (*func)(int x);  
  2. void up(int s);  
  3. func f= up;  
  4. f(3);  


 


func是個函數指針類型:返回值是void,參數是一個int的函數。所以func的變量可以指向所有這一類的函數。
這是C風格的函數指針。但是在cocos2d-x中的回調,雖然還是函數指針,但已經有所區別。准確點說應該是成員函數指針。那么這普通的函數指針還可以來調成員函數嗎?呵呵,如果能的話我就不用寫這篇文章了。
C風格的函數指針要想調用成員函數,那么這個成員函數如果是static的也可以(為什么靜態函數就可以,呵呵)。但是這樣的話就會破壞類的結構。看cocos2d-x的實現也不是這樣的。
這里說cocos2d-x的實現方式:
看上面的定義,如:typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
看這個就應該大致可以知道它的實現了。
這個定義有點不一樣,就是這個函數是CCObject的成員函數。這就是成員函數指針的定義。
大家知道,成員函數不能像普通C風格的函數那樣調用,因為每個成員函數需要知道是哪個對象實例調用它的,隱含有一個this指針。這也解釋了為什么靜態函數可以用C風格的函數指針來回調,因為靜態函數不需要對象實例就可以調用,呵呵。
既然定義成員函數指針,那么要用這個指針變量來調用回調函數,還需不需要對象實例呢。毫無疑問,還是需要的。
所以還必須有一個回調對象,CCObject *m_pListener。
這樣調用: 

[cpp]  view plain copy
  1. (m_pListener->*m_pSelector)(CCObject *param);  



下面是我寫的一個demo,類似cocos2d-x的實現:
[cpp]  view plain copy
  1. #ifndef __TestCallBack__Person__  
  2. #define __TestCallBack__Person__  
  3.   
  4. #include <iostream>  
  5. #include <string>  
  6.   
  7. using namespace std;  
  8.   
  9. // 基類  
  10. class Person {  
  11.   
  12. public:  
  13. void name(string name);  
  14. };  
  15.   
  16. // 定義基類的成員函數指針  
  17. typedef void (Person::*SEL_CallFun)(string str);  
  18.   
  19.   
  20. // 派生類  
  21. class Student : public Person{  
  22. private:  
  23. string m_name;  
  24. int m_age;  
  25.   
  26. public:  
  27. Student(string name, int age);  
  28. ~Student();  
  29.   
  30. // 回調  
  31. void callBack(string str);  
  32.   
  33. // say方法,要調用回調函數。  
  34. void say();  
  35. protected:  
  36. // 回調的執行者  
  37. Person *m_pListen;  
  38.   
  39. // 回調函數指針  
  40. SEL_CallFun m_pfnSelectior;  
  41. };  



實現:
[cpp]  view plain copy
  1. #include "Person.h"  
  2.   
  3. void Person::name(string name)  
  4. {  
  5. cout<<name<<endl;  
  6. }  
  7.   
  8. Student::Student(string name, int age)  
  9. {  
  10. this->m_name = name;  
  11. this->m_age = age;  
  12. }  
  13.   
  14. Student::~Student()  
  15. {  
  16.   
  17. }  
  18.   
  19. void Student::say()  
  20. {  
  21. cout<<"Hi this is a Student"<<endl;  
  22.   
  23. // 回調函數指針賦值。需要強轉成 SEL_CallFun  
  24. m_pfnSelectior = (SEL_CallFun)(&Student::callBack);  
  25.   
  26. // 回調的執行對象,傳this  
  27. m_pListen = this;  
  28.   
  29. // 調用回調,參數是個string  
  30. (m_pListen->*m_pfnSelectior)(m_name);  
  31. }  
  32.   
  33. // 成員函數,要回調的函數  
  34. void Student::callBack(string str)  
  35. {  
  36. cout<<"My name is "  
  37. << str<<endl  
  38. << "age is "  
  39. <<m_age<<endl;  
  40. }  



main
[cpp]  view plain copy
  1. #include <iostream>  
  2. #include "Person.h"  
  3.   
  4. int main(int argc, const char * argv[])  
  5. {  
  6.   
  7. Student *a = new Student("Join",20);  
  8. a->say();  
  9. return 0;  
  10. }  


輸出:
[cpp]  view plain copy
  1. Hi this is a Student  
  2. My name is Join  
  3. age is 20  



如果再定義一個宏:
[cpp]  view plain copy
  1. #define callFunc_selector(_SELECTOR) (SEL_CallFun)(&_SELECTOR)  


那么調用就改成:
[cpp]  view plain copy
  1. m_pfnSelectior = callFunc_selector(Student::callBack);  

這個就是cocos2d-x的回調實現模式了。呵呵
仔細看看,是不是一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM