我正在为游戏实现一个事件系统。它使用事件队列和数据结构来保存给定事件类型的所有已注册事件处理程序。到目前为止注册处理程序工作正常,但是当涉及到注销它们时(例如,当游戏对象被销毁时会发生的事情)我在模板和转换方面遇到了一些麻烦。
我将 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);
}
然后,在模板类 EventHandler 上,像这样实现抽象方法“equal”:
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)。有没有办法执行它,或者至少有一些解决方法可以解决问题?
提前致谢 =)
最佳答案
通常在关闭模板时,您需要确保 > 由空格分隔,这样编译器就不会将它们解析为右移运算符。
在这里,您试图将一个引用静态转换为一个非引用,即使它有效也可以调用对象切片。您需要静态转换为派生引用。
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();
}
关于c++ - 将非模板基类向下转换为模板化派生类 : is it possible?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2388643/