cocos2d-x遊戲開發(十三)細說回呼函數

來源:互聯網
上載者:User

歡迎轉載:http://blog.csdn.net/fylz1125/article/details/8546607


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

typedef void (CCObject::*SEL_SCHEDULE)(float);// 用來調updatetypedef void (CCObject::*SEL_CallFunc)();// 用來自訂無參回調typedef void (CCObject::*SEL_CallFuncN)(CCNode*);// 帶執行者回調typedef void (CCObject::*SEL_CallFuncND)(CCNode*, void*); // 帶一個自定參數的回調typedef void (CCObject::*SEL_CallFuncO)(CCObject*);typedef void (CCObject::*SEL_MenuHandler)(CCObject*);typedef void (CCObject::*SEL_EventHandler)(CCEvent*);typedef int (CCObject::*SEL_Compare)(CCObject*);#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)#define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)#define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)#define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)#define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)#define event_selector(_SELECTOR) (SEL_EventHandler)(&_SELECTOR)#define compare_selector(_SELECTOR) (SEL_Compare)(&_SELECTOR)


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

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

比如:

typedef void (*func)(int x);void up(int s);func f= up;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。
這樣調用:

(m_pListener->*m_pSelector)(CCObject *param);

下面是我寫的一個demo,類似cocos2d-x的實現:

#ifndef __TestCallBack__Person__#define __TestCallBack__Person__#include <iostream>#include <string>using namespace std;// 基類class Person {public:void name(string name);};// 定義基類的成員函數指標typedef void (Person::*SEL_CallFun)(string str);// 衍生類別class Student : public Person{private:string m_name;int m_age;public:Student(string name, int age);~Student();// 回調void callBack(string str);// say方法,要調用回呼函數。void say();protected:// 回調的執行者Person *m_pListen;// 回呼函數指標SEL_CallFun m_pfnSelectior;};

實現:

#include "Person.h"void Person::name(string name){cout<<name<<endl;}Student::Student(string name, int age){this->m_name = name;this->m_age = age;}Student::~Student(){}void Student::say(){cout<<"Hi this is a Student"<<endl;// 回呼函數指標賦值。需要強轉成 SEL_CallFunm_pfnSelectior = (SEL_CallFun)(&Student::callBack);// 回調的執行對象,傳thism_pListen = this;// 調用回調,參數是個string(m_pListen->*m_pfnSelectior)(m_name);}// 成員函數,要回調的函數void Student::callBack(string str){cout<<"My name is "<< str<<endl<< "age is "<<m_age<<endl;}

main

#include <iostream>#include "Person.h"int main(int argc, const char * argv[]){Student *a = new Student("Join",20);a->say();return 0;}

輸出:

Hi this is a StudentMy name is Joinage is 20

如果再定義一個宏:

#define callFunc_selector(_SELECTOR) (SEL_CallFun)(&_SELECTOR)

那麼調用就改成:

m_pfnSelectior = callFunc_selector(Student::callBack);

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.