65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 多播事件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (7投票s)

2014年1月8日

CPOL

2分钟阅读

viewsIcon

14737

downloadIcon

280

用于在 C++ 中声明和定义多播事件源和接收器的辅助工具

介绍 

许多编程语言原生提供某种形式的事件处理机制,包括委托。网络上有很多优秀的解决方案,例如 成员函数指针和最快的 C++ 委托 [^],这仍然是我最喜欢的 CodeProject 文章之一,或者 Boost [^]Loki [^],这些是我首先想到的库。

提供的源代码提供了一种基本解决方案,用于在 C++ 中声明和定义多播事件源和事件接收器。

背景

提供的解决方案大量使用宏来

  • 定义模板化的基类,这些基类可用于声明和定义事件源;
  • 定义基类,这些基类可用于声明和定义事件接收器。

使用宏和继承来解决问题的一个少数积极方面是,可以生成易于阅读的事件 getter 方法名称。

另一方面,宏的所有负面影响,尤其是复杂的宏,是众所周知的。新的 C++ 语言特性也为新的方法提供了大量的机会。

该解决方案也没有提供指定签名中返回类型的方法。可以轻松添加它,但我认为这需要额外的处理才能真正保持一致,正如我在 这个 C# 技巧 [^] 中尝试展示的那样,因此它可能属于后续版本。

使用代码 

附带的源代码包含头文件 MulticastEvent.h,这是使用该库所需的唯一文件。

#include "MultiCastEvent.h" 

事件签名可以这样定义:

#define MULTICAST_EVENT_CALLED_A (ClassExposingEvents, MethodACalledEvent, int, x, int, y)
#define MULTICAST_EVENT_CALLED_B (ClassExposingEvents, MethodBCalledEvent)

事件源可以使用事件签名这样定义:

// a class which exposes two events named MethodACalledEvent and MethodBCalledEvent
class ClassExposingEvents
{
public:
    ClassExposingEvents() 
        // initialize the multicast target lists
        : MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_A)
        , MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_B)
    {};
    ~ClassExposingEvents() {};
public:
    // declare and define the two events
    DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_A);
    DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_B);
public:
    // two example methods which invoke the events and report themselfes
    void a(int x, int y) { getMethodACalledEvent().invoke(x, y); /* 2do: add code */ };
    bool b() { getMethodBCalledEvent().invoke(); /* 2do: add code */ return true; };
};

事件接收器可以类似地定义:

// a class which sinks the two exposed events of ClassExposingEvents to report on invocation
class ClassImplementingEventHandlers 
    // implement the interfaces of the events
    : public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_A)
    , public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_B)
{
public:
    ClassImplementingEventHandlers() {};
    ~ClassImplementingEventHandlers() {};

public:
    // declare or inline define the event handlers to report when being invoked
    DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_A) /* or define it inline */;
    DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_B) /* or define it inline */; 
};

// define the event handlers if they haven't got inline defined to report when being invoked
DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_A)
{
    // todo: add handler code
}

DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_B)
{
    // todo: add handler code
}

实例化后,源和接收器可以像这样路由:

// define event sources
ClassExposingEvents eventSource;

// define event sinks
ClassImplementingEventHandlers eventSink;

// create routes
eventSource.getMethodACalledEvent().addListener(eventSink); 

兴趣点 

提供的源代码非常基础,仅提供作为进一步开发的起点所需的最低限度。既没有考虑线程安全,也没有考虑性能、内存使用或其他方面。

历史 

  • 2014/01/08:提交了第一个版本。
© . All rights reserved.