2016-08-17 225 views
0

我无法编译std::static_pointer_cast<>()时发现以下错误修复,抛出: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()在类中定义为类型,用于标识类类型。

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。这是真的?如果是这样,我如何设置我的层次来允许这种类型的转换?

如果情况并非如此,上述静态转换的问题是什么?

回答

0

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

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

您可以尝试提高上。

+0

谢谢你帮助我理解。在你和erenon的回答之间,我收集了这个内容,而不是在Subscription Manager模板中使用BaseEvent,我应该创建一个BaseEventSubscriptionManager进入std :: unordered_map模板。 – mstehula

+0

我把你提供的链接和编辑它,以显示我的新方向,只是这样我可以保存它以备后用。 [链接](http://coliru.stacked-crooked.com/a/729d9edd5a4d331a) – mstehula

1

在C++中,没有协方差或逆变,有T<Base>和​​之间没有关系,即使存在BaseSub之间的一个。

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