2014-01-17 25 views
1

我正在尝试在C++中编写通用自定义事件类。事件处理程序是一个类成员函数。所以,我用一个映射来存储对象和事件处理函数指针。以下是我的班级定义。在C++中编写自定义事件类

* 错误C2923:

class EventArgs 
{ 
public: 
    void* m_object; 
public: 
    EventArgs(void* obj) 
    { 
     m_object = obj; 
    } 
}; 

// templated function pointer that can point to any class member function 
// which takes in a EventArgs* and returns void 
template<typename T> 
struct TFunctr 
{ 
    void (T::*EventHandler)(EventArgs* ev); 
}; 

template<typename T> 
class Event 
{ 
protected: 
    map<T,TFunctr<T>::EventHandler> m_eventHandlers; // store the member function pointer along with the object. 

    void addListener(T object, TFunctr<T> handler) 
    { 
     m_eventHandlers[object] = handler; 
    } 

    void removeListener(T object, TFunctr<T> handler) 
    {  
     m_eventHandlers.erase(object); 
    } 

    virtual void fire(EventArgs* ev) 
    { 
     // ensure that there are subscribers(listeners) for this event 
     if(!m_eventHandlers.empty()) 
     { 
      for(map<T, TFunctr<T>>::iterator iter = m_eventHandlers.begin(); iter != m_eventHandlers.end(); ++iter) 
      { 
       T obj = iter->first;     // get the object 
       TFunctr<T>::EventHandler hnd = (TFunctr<T>::EventHandler) iter->second; // get the member function ptr 

       (obj.*hnd)(ev); // invoke the function 
      } 
     } 
    } 

    virtual ~Event() 
    { 
     // clear the eventhandlers list 
     m_eventHandlers.clear();   
    } 
}; 

我在第25行得到一个编译错误 '的std ::地图': 'TFunctr ::事件处理程序' 不是参数的有效模板类型参数“ _Ty'*

感谢您在修复这些问题上的帮助。

我无法升级到C++ 11,因为代码是针对g ++ 4.1.2的。 我已阅读关于boost库(信号和插槽),但我想保留它作为最后的手段。

(我在C#中一直致力于和最近搬到了一个项目,该项目是在C++中,所以,我在了解了C++的语法和语义的难度。)提前

感谢。

+1

当询问编译错误时:** 1。**发布完整的和未编辑的错误消息(除非它是嵌套模板错误的页面,在这种情况下发布前几个和最后几个),** 2. * *表明发生错误的源代码行。如果该行是一个复杂的表达式,请将其分解为几个语句,再次编译,然后将其发布到此处。 – Angew

+1

加油。你会遇到编译错误,为什么不把它们包含在问题中。你希望大家只是猜测这个问题? – John3136

+0

对不起,我错过了发布错误。我已经用确切的错误信息更新了我的问题,并且我无法使用C++ 11,因为它针对的是g ++ 4.1.2。你能建议吗?谢谢 – user1333222

回答

1

我无法回答你的编译错误,因为你没有发布它们,但如果你有权访问C++ 11,那么你可以使用std::function类来简化处理回调/监听器:

class EventArgs 
{ 
public: 
    void* m_object; 
public: 
    EventArgs(void* obj) 
    { 
     m_object = obj; 
    } 
}; 

template<typename T> 
class Event 
{ 
    std::vector<std::function<void(T&)> m_EventHandlers; 

public: 

    void addListener(std::function<void(T&)> handler) 
    { 
    m_EventHandlers.push_back(handler) 
    } 

    void removeListener(std::function<void(T&)> handler) 
    { 
    // etc etc 
    } 

    virtual void fire(EventArg &args) 
    { 
    for(auto handler : m_EventHandlers) 
    { 
     handler(args); 
    } 
    } 
}; 

现在,你可以说:

Event event; 
event.addListener([](Event &e){std::cout << "got an event";}) 

注:我已经改变了事件参数的引用,表明总有和事件对象。如果它没有(这似乎不太可能)是有效的,那么将它转回到一个指针。我已经将它作为非const来允许处理程序修改事件中的数据,这更符合C#事件的工作方式。

+0

+1。您可能还想建议将这些'T *'转换为'const T':) –

+0

我已经更新了我的问题,并提供了确切的错误消息,并且我无法使用C++ 11,因为它针对的是g ++ 4.1.2 。你能建议吗?谢谢。 – user1333222