在 C++ 中编写自定义事件类

Writing custom events class in C++

本文关键字:自定义 事件 C++      更新时间:2023-10-16

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

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 行收到编译错误:

*错误 C2923:"std::map":"TFunctr::事件处理程序"不是参数"_Ty"的有效模板类型参数*

感谢您在解决这些问题方面的帮助。

我无法升级到 C++11,因为代码针对的是 g++ 4.1.2。我已经阅读了有关升压库(信号和插槽)的信息,但我想将其作为最后的手段。

(我一直在用 C# 工作,最近转到了一个C++的项目。所以,我很难理解C++语法和语义。

提前谢谢。

我无法回答您的编译错误,因为您尚未发布它们,但是如果您可以访问 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";})

注意:我已将事件参数更改为引用,以指示始终存在 和 事件对象。如果它有效,不存在(这似乎不太可能),然后将其转回指针。我将其保留为 non-const 以允许处理程序修改事件中的数据,这更符合 C# 事件的工作方式。