static_pointer_cast通过继承和模板

时间:2016-08-17 19:36:45

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

我无法在编译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<E>类和模板,TestEvent继承了Event<TestEvent> BaseEvent。这是真的?如果是这样,我如何设置我的层次结构以允许这种类型的转换?

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

2 个答案:

答案 0 :(得分:1)

在C ++中,没有协方差或逆变,T<Base>T<Sub>之间没有关系,即使BaseSub之间存在关联。

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

答案 1 :(得分: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);
}

你可以尝试改进。