我正在实现一个游戏的事件系统。它使用事件队列和数据结构来保存给定事件类型的所有注册事件处理程序。它到目前为止工作正常,注册处理程序,但是当涉及到注销它们(例如,当游戏对象被销毁时将发生的事情),我在模板和铸造方面有点麻烦。将非模板基类向下转换为模板派生类:是否有可能?
我已经定义了一个EventHandler作为某种函数,部分基于Szymon Gatner的文章http://www.gamedev.net/reference/programming/features/effeventcpp/。准确地说,我把HandlerFunctionBase和MemberFunctionHandler类的定义和想出了:
class BaseEventHandler
{
public:
virtual ~BaseEventHandler(){}
void handleEvent(const EventPtr evt)
{
invoke(evt);
}
private:
virtual void invoke(const EventPtr evt)=0;
};
template <class T, class TEvent>
class EventHandler: public BaseEventHandler
{
public:
typedef void (T::*TMemberFunction)(boost::shared_ptr<TEvent>);
typedef boost::shared_ptr<T> TPtr;
typedef boost::shared_ptr<TEvent> TEventPtr;
EventHandler(TPtr instance, TMemberFunction memFn) : mInstance(instance), mCallback(memFn) {}
void invoke(const EventPtr evt)
{
(mInstance.get()->*mCallback)(boost::dynamic_pointer_cast<TEvent>(evt));
}
TPtr getInstance() const{return mInstance;}
TMemberFunction getCallback() const{return mCallback;}
private:
TPtr mInstance;
TMemberFunction mCallback;
};
然后对我想过的eventmanager进行类unregisterHandler()方法,初步实现会是这样的:
// EventHandlerPtr is a boost::shared_ptr<BaseEventHandler>.
// mEventHandlers is an STL map indexed by TEventType, where the values are a std::list<EventHandlerPtr>
void EventManager::unregisterHandler(EventHandlerPtr hdl,TEventType evtType)
{
if (!mEventHandlers.empty() && mEventHandlers.count(evtType))
{
mEventHandlers[evtType].remove(hdl);
//remove entry if there are no more handlers subscribed for the event type
if (mEventHandlers[evtType].size()==0)
mEventHandlers.erase(evtType);
}
}
使“删除”在这里工作我想重载==操作符BaseEventHandler,然后使用虚拟方法来执行实际比较的......
bool BaseEventHandler::operator== (const BaseEventHandler& other) const
{
if (typeid(*this)!=typeid(other)) return false;
return equal(other);
}
,并在模板类事件处理程序,实现抽象方法“平等”是这样的:
bool equal(const BaseEventHandler& other) const
{
EventHandler<T,TEvent> derivedOther = static_cast<EventHandler<T,TEvent>>(other);
return derivedOther.getInstance() == this->getInstance() && derivedOther.getCallback()==this->getCallback();
}
当然,我上线的static_cast得到一个编译错误。我甚至不确定是否有可能做到这一点(不一定使用static_cast)。有没有一种方法来执行它,或者至少有一些解决方法可以做到这一点?
在此先感谢=)
您至少可以转换为引用类型而不是'derivedOther',试图成为“其他”参数的*副本*。我担心你的问题对于我现在彻底明白这一点有些太长了,所以我不确定这是一个小问题还是正确的答案。一般建议:请记住,具有不同模板参数的两个不同的EventHandler类是不相关的,它们恰好是使用相同的源创建的。除非指定T和TEvent,否则没有'EventHandler'这样的类型,所以'other'最好与'this'具有相同的类。 –
2010-03-05 17:31:01
你应该包含你得到的编译错误。另一个注意:为什么'equal()'没有在模板类EventHandler中声明? – 2010-03-05 17:42:16