我想创建一个事件调度系统,其事件(浅层)可以通过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; }
};
(这完全是Double dispatch/multimethods in C++和Wikipedia article on double dispatch)
的引导现在,当我调试双重调度时,调用派生的Event类(beObservedBy
的{{1}}方法,然后使用派生的EventObserver类,但是{{1}调用函数而不是EventA
我做错了吗?我尝试使用引用而不是指针而没有爱。
答案 0 :(得分:2)
问题是您在ObserverX中定义observe(EventA *evt)
。
这会导致函数重载。
但是当您致电observe
时,参数为BaseEvent *
而非EventA *
。所以改为调用基类方法。
派生类中的签名必须与基类中的签名匹配,否则它不会覆盖它,它只是重载它(所以你最终得到两个函数 - 一个取EventA *
而另一个取{需要BaseEvent *
)。
尝试在ObserverX中定义observe(BaseEvent *evt)
。
答案 1 :(得分:1)
您的基本观察者类需要知道如何观察任何事件类型,或者您的基本事件类需要知道任何观察者类型如何观察。否则,您的双重发送只会丢失从初始发送中获得的类型信息。
在您的情况下,如果您将virtual void observe( EventA* evt )
添加到BaseObserver
课程,则EventA::beObservedBy
会调用该版本的观察方法,而ObserverX
会正确覆盖它。
答案 2 :(得分:0)
首先,ObserverX中的observe签名与Base类中的签名不同,它不会覆盖基类中的虚拟void observe(BaseEvent * evt)方法。相反,您正在定义一个以EventA *作为参数的新函数。
请记住,在C ++中,函数签名由函数名和参数列表组成,在本例中为
virtual void observe( BaseEvent* evt )
与
不同virtual void observe( EventA* evt )