c++ - 将非模板基类向下转换为模板化派生类 : is it possible?

标签 c++ templates event-handling casting

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

我将 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/

相关文章:

C++编译错误: unexpected type name 'string' : expected expression

c++ - 从 C 代码中调用 R 脚本

c++ - 是否可以在 C++ 中使用 "bundle"模板参数?

c++ - 这被认为是显式 C++ 模板类实例化吗?

c++ - 识别 QT 中正则表达式匹配的组

c++ - 这种类型和功能是否存在现有名称?

c++ - 与普通 POD 类型相比,如何克服仅包含一个 POD 成员的简单类的性能下降?

c# - ASP.NET/HTML : HTML button's onClick property inside ASP. 网络 (.cs)

c# - 控制应用程序流程的问题

javascript - 如何将普通js函数注册到 Angular 中的@Output