我正在實現一個遊戲的事件系統。它使用事件隊列和數據結構來保存給定事件類型的所有註冊事件處理程序。它到目前爲止工作正常,註冊處理程序,但是當涉及到註銷它們(例如,當遊戲對象被銷燬時將發生的事情),我在模板和鑄造方面有點麻煩。將非模板基類向下轉換爲模板派生類:是否有可能?
我已經定義了一個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