2016-08-17 222 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)的共同祖先,並使用該實例或提供轉換構造函數。