1

我想创建一个具有事件(浅)层次结构的事件调度系统,可以通过 EventObservers 的(浅)层次结构观察。我认为双重调度将允许各种各样的事件和事件观察者,而不必为每个组合都提供一个函数。

我有这样的代码:

class BaseObserver;

class BaseEvent {
public:

    virtual std::string getName() { return "BaseEvent"; }

    void beObservedBy( BaseObserver* obv );

};

class BaseObserver {
public:

    virtual void observe( BaseEvent* evt ) {

        std::cout << "BaseObserver observing: " << evt->getName() << "." << std::endl;

    }

};

void BaseEvent::beObservedBy( BaseObserver* obv ) { obv->observe( this ); }

然后定义几个测试类:

class EventA : public BaseEvent {
public:

    void beObservedBy( BaseObserver* obv ) { obv->observe( this ); }

    virtual std::string getName() { return "I am an EventA"; }

};

class EventB : public BaseEvent {
public:

    void beObservedBy( BaseObserver* obv ) { obv->observe( this ); }

    virtual std::string getName() { return "I am an EventB"; }

};

class ObserverX : public BaseObserver {

    virtual void observe( EventA* evt  ) {  std::cout << "ObserverX spotted an EventA" << std::endl; }

};

(这一切都遵循C++ 中的 Double dispatch/multimethodsWikipedia article on double dispatch

现在当我调试双重调度时,调用beObservedBy了派生Event类(EventA比如说)的方法,并使用了派生EventObserver类,但是observe( BaseEvent* )调用的是函数而不是observe( EventA* )

我做错了吗?我尝试使用引用而不是指针,但没有得到爱。

4

3 回答 3

2

问题是你observe(EventA *evt)在 ObserverX 中定义的。这会导致函数重载。但是当你调用时observe,参数是BaseEvent *而不是EventA *。因此,改为调用基类方法。

派生类中的签名必须与基类中的签名匹配,否则它不会覆盖它,它只是重载它(因此您最终会得到两个函数 - 一个接受EventA *,一个接受BaseEvent *)。

尝试observe(BaseEvent *evt)在 ObserverX 中定义。

于 2011-05-25T22:48:44.717 回答
1

您的基本观察者类需要知道如何观察任何事件类型,或者您的基本事件类需要知道如何被任何观察者类型观察。否则,您的双重派送只会丢失从您的初始派送中获得的类型信息。

在您的情况下,如果您添加virtual void observe( EventA* evt )到您的BaseObserver类中,那么EventA::beObservedBy将调用该版本的观察方法并ObserverX正确覆盖它。

于 2011-05-25T22:56:09.483 回答
0

首先, ObserverX 中的 observe 签名与 Base 类中的不同,它没有覆盖基类中的 virtual void observe( BaseEvent* evt ) 方法。相反,您正在定义一个以 EventA* 作为参数的新函数。

请记住,在 C++ 中,函数签名由函数名称和参数列表组成,在这种情况下

virtual void observe( BaseEvent* evt )

不同于

virtual void observe( EventA* evt )
于 2011-05-25T22:47:59.990 回答