2010-02-06 137 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

相关问题