函數指針一般來說必須返回類型和參數類型一一嚴格對應,否則有可能導致問題,即使參數類型本身是父子關係。
比如如果想自定義一個通知對象來取代通知回調函數中CCObject參數:
typedef void (CCObject::*SEL_NotifyFunc)(NotificationObj*);
class NotificationObj : public CCObject {
public:
NotificationObj(void *data) { this->data = data; }
void *data;
};
class MyMsgCenter : public GameCenter, CCObject { // 一時疏忽,忘記給CCObject加上puclic了
public:
MyMsgCenter();
void MyMsgCenter::handleLogic(NotificationObj *obj); // NotificationObj繼承CCObject
}
MyMsgCenter::MyMsgCenter() {
NotificationCenter* center = CCNotificationCenter::sharedNotificationCenter();
center->addObserver(this, callfuncO_selector(MyMsgCenter::handleLogic), "xxx", NULL); // 直接強制轉換
}
真正運行接收通知的時候,詭異問題出現了,發現自動(暗地裏)產生了另外一個MyMsgCenter對象, 由於CCObject是以私有繼承方式繼承,編譯器這時候處理的時候認爲當前的MyMsgCenter對象也許不是最適合的處理對象,就給你創造了一個臨時的對象出來了。
如果改成 class MyMsgCenter : public GameCenter, public CCObject 是沒有問題的。另外,不修改public,也可以這樣達到正確的目的:
center->addObserver(this, (SEL_CallFuncO)((SEL_NotifyFunc)(&MyMsgCenter::handleLogic)), "xxx", NULL);
經過兩次轉換之後,不再自動產生MyMsgCenter對象了,也就是你已經顯示的告知編譯器我這個函數是長什麼樣了。