2010-02-06 90 views
2

所以我正在處理這個事件管理類。我存儲了指向void (Event*)簽名的成員函數的指針列表,其中Event只是當前存儲一些隨機數據的結構。成員函數帶有基類參數的指針接受派生類參數

typedef boost::function<void(Event*)> Callback; 
typedef vector<Callback> CallbackList; 

class EventManager 
{ 
public: 
    template<typename T> 
    void RegisterEventHandler(const std::string& type, void (T::*handler)(Event*), T* obj) 
    { 
     mCallbackList[type].push_back(boost::bind(handler, obj, _1)); 
    } 

    void DispatchEvent(const std::string& type, Event* evt) 
    { 
     for(CallbackList::iterator it = mCallbackList[type].begin(); it != mCallbackList[type].end(); ++it) 
     { 
     Callback callback = (*it); 
     callback(evt); 
     } 
    } 
private: 
    hash_map<std::string, CallbackList> mCallbackList; 
}; 

我想知道,如果有可能,我推導出不同版本的事件,並通過指針的成員函數到這個班?目前我正在嘗試這個。

class MouseEvent : public Event 
{ 
public: 
    int testMouseData1; 
    int testMouseData2; 
    int testMouseData3; 
}; 

class HelloWorld 
{ 
public: 
    void Display(MouseEvent* evt) 
    { 
     cout << "Hello, world!" << endl; 
    } 
}; 


int main(void) 
{ 
    MouseEvent* evt = new MouseEvent(); 

    HelloWorld* world = new HelloWorld(); 
    eventManager->RegisterEventHandler("testType", &HelloWorld::Display, world); 

    return 0; 
} 

這給了我XCode中的以下錯誤。

error: no matching function for call to ' EventManager::RegisterEventHandler(const char [9], void (HelloWorld::*)(MouseEvent*), HelloWorld*&) '

你知道我該如何安全地傳遞一個指針,它的函數簽名中需要派生類嗎?謝謝。

回答

2

所以我找到了一個解決方案,似乎爲我工作,但我不知道是否完全安全。我改變了RegisterEventHandler方法施放的所有函數指針,我發送到同一類型的...

template<typename T1, typename T2> 
    void RegisterEventHandler(const String& type, T1 handler, T2* obj) 
    { 
     void (T2::*evtHandler)(Event*) = (void (T2::*)(Event*)) (handler); 
     mCallbackList[type].push_back(boost::bind(evtHandler, obj, _1)); 
    } 

現在這一切似乎我原本打算只是工作。但我對這一切都很陌生,所以我不完全確定這是否安全。有什麼想法嗎?謝謝

1

如果您的原型預計「事件」類型,那麼您需要確保void Display(MouseEvent* evt)函數接受「Event」類型。因此,將其更改爲void Display(Event *evt)然後在通話內部,您可以將其轉回MouseEvent,假設來電者通過了一個實際的MouseEvent,引用爲「Event」。

其次,我相信你可能在調用RegisterEventHandler時會遇到一些其他問題,因爲它在模板中,但是你沒有指定模板類型。

+0

@哈利 - 模板函數有類型推斷,所以我會說他調用RegisterEventHandler的方式是OK – Manuel 2010-02-06 18:06:36

+0

函數模板參數可以從函數參數中推斷出來,但是顯式指定模板類型將有助於確定爲什麼實例化失敗 – Anycorn 2010-02-06 18:07:11

+0

同意,只是試圖消除這裏的所有變量。很確定@Morgan需要看的主要觀點是「事件」類型與「MouseEvent」。 – 2010-02-06 18:18:36

相關問題