【问题标题】:static_pointer_cast through inheritance and templatestatic_pointer_cast 通过继承和模板
【发布时间】:2016-08-17 19:36:44
【问题描述】:

在编译std::static_pointer_cast<>() 时抛出以下错误,我无法找到解决方法:

error: invalid static_cast from type ecse::EventSubscriptionManager<ecse::BaseEvent>* to type ecse::EventSubscriptionManager<TestEvent>*

我有以下层次结构。最后,它们将被 POD 类型的成员填充,并且很可能会变成结构。

class BaseEvent {};

template <class E>
class Event : public BaseEvent, public Type<E> {};

class TestEvent : public Event<TestEvent> {};

我目前正在处理 EventManager 的订阅功能部分,但是在编译时我收到了上面发布的错误。注意:E::ID()在类中定义为Type,用于标识类类型。

template <class E>
class EventSubscriptionManager
{
public:
  void Subscribe(std::function<void(E)>  fptr);
private:
  std::function<void(E)> event_function_;
};

class EventManager
{
public:
  template <class E>
  void Subscribe(std::function<void(E)> fptr)
  {
     std::shared_ptr<EventSubscriptionManager<E>> sub_manager_ptr;
     auto sub_manager_iterator = sub_managers_.find(E::ID());
     if(sub_manager_iterator == sub_managers_.end())
     {
       sub_manager_ptr = std::make_shared<EventSubscriptionManager<E>>();
     }
     else
     {
       sub_manager_ptr = std::static_pointer_cast<EventSubscriptionManager<E>>(sub_manager_iterator->second);
     }
     // Continue function...
  }
private:
  std::unordered_map<std::size_t, std::shared_ptr<EventSubscriptionManager<BaseEvent>>> sub_managers_;
}

我认为问题在于TestEventBaseEvent 之间存在Event&lt;E&gt; 模板类,TestEvent 继承Event&lt;TestEvent&gt; 而不是BaseEvent。这是真的?如果是这样,我如何设置我的层次结构以允许这种类型的转换?

如果不是这样,上面的静态转换有什么问题?

【问题讨论】:

    标签: c++ templates c++11 inheritance


    【解决方案1】:

    我可以告诉你为什么它不能编译。这是因为

    EventSubscriptionManager<E>
    

    无关
    EventSubscriptionManager<BaseEvent>
    

    所以,根据参考页面上的point 1.)

    static_cast<EventSubscriptionManager<E>*>((EventSubscriptionManager<BaseEvent>*)nullptr)
    

    格式不正确。

    但是,在不知道背景的情况下,我不知道该怎么做作为解决方法。 只是:您必须将这两个类关联起来,或者选择一个全新的设计。



    为了做到这一点,here 是它失败的一个最小示例,这可能会有所帮助:

    struct Base {};
    struct Derived : Base {};
    
    template<typename T>
    struct Foo {};
    
    int main()
    {
       static_cast<Foo<Derived>*>((Foo<Base>*)nullptr);
    }
    

    您可以尝试对此进行改进。

    【讨论】:

    • 感谢您帮助我理解。在你和 erenon 的回答之间,我收集到,我应该创建一个 BaseEventSubscriptionManager 来进入 std::unordered_map 模板,而不是在 Subscription Manager 模板中使用 BaseEvent。
    • 我获取了您提供的链接并对其进行了编辑以显示我的新方向,以便我可以将其保存以备后用。 link
    【解决方案2】:

    在 C++ 中,没有协变或逆变,T&lt;Base&gt;T&lt;Sub&gt; 之间没有关系,即使 BaseSub 之间存在一个关系。

    您要么需要构建不同 EventSubscriptionManager 实例的共同祖先(例如:EventSubscriptionManagerBase)并使用它,要么提供转换构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多