多繼承下函數指針強制轉換所引發的詭異問題(CCNotificationCenter)

  函數指針一般來說必須返回類型和參數類型一一嚴格對應,否則有可能導致問題,即使參數類型本身是父子關係。

  比如如果想自定義一個通知對象來取代通知回調函數中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對象了,也就是你已經顯示的告知編譯器我這個函數是長什麼樣了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章