将非模板基类向下转换为模板化派生类:是否可能? [英] Downcasting non-template base class to templated derived class: is it possible?

查看:115
本文介绍了将非模板基类向下转换为模板化派生类:是否可能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为游戏实施事件系统。它使用事件队列和数据结构来保存给定事件类型的所有已注册事件处理程序。到目前为止,它可以很好地注册处理程序,但是要注销它们(例如,当游戏对象被销毁时会发生这种情况),我在模板和转换方面遇到了一些麻烦。

I'm implementing an event system for a game. It uses an event queue, and a data structure to hold all registered event handlers for a given event type. It works fine so far registering handlers, but when it comes to unregistering them (something that will take place when a game object is destroyed, for instance) I'm having a bit of trouble regarding templates and casting.

我已将EventHandler定义为某种函子,部分基于Szymon Gatner在 http://www.gamedev.net/reference/programming/features/effeventcpp/ 。确切地说,我采用了HandlerFunctionBase和MemberFunctionHandler类的定义,并提出了:

I've defined an EventHandler as some sort of functor, partially based on Szymon Gatner's article on http://www.gamedev.net/reference/programming/features/effeventcpp/ . To be precise, I took the HandlerFunctionBase and MemberFunctionHandler class definitions and came up with:

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()方法的初始实现像这样:

Then the initial implementation for the unregisterHandler() method on the EventManager class I've thought of would go like this:

// 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的==运算符,然后使用虚拟方法执行实际比较...

To make "remove" work here I thought of overloading the == operator for BaseEventHandler, and then using a virtual method to perform the actual comparison...

bool BaseEventHandler::operator== (const BaseEventHandler& other) const
{
    if (typeid(*this)!=typeid(other)) return false;
    return equal(other);
}

,然后在模板类EventHandler上实现抽象方法等于,例如

and, on the template class EventHandler, implement the abstract method 'equal' like this:

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)。有没有一种方法可以执行它,或者至少有一些解决方法可以达到目的?

Of course, I'm getting a compile error on the static_cast line. I'm not even sure that it is possible at all to do that cast (not necessarily using static_cast). Is there a way to perform it, or at least some workaround that does the trick?

在此先感谢=)

推荐答案

通常,在关闭模板时,需要确保>由空格分隔,以便编译器不会将它们解析为右移运算符。

In general when closing templates, you need to make sure that > are separated by spaces so the compiler doesn't parse them as a right-shift operator.

在这里,您试图将一个引用静态转换为非引用,即使非引用也可以调用对象切片。您需要将静态转换为派生引用。

Here you're trying to static cast a reference to a non-reference, which even if it worked could invoke object slicing. You need to static cast to a derived reference.

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();
}

这篇关于将非模板基类向下转换为模板化派生类:是否可能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆