2015-04-01 77 views
1

我有一個從模板定義類型繼承的類型。模板定義的類型保證有一個給定的基類。我想要做的是能夠dynamic_cast或以其他方式查找與匹配派生類型的容器中的類型,而不考慮模板參數。dynamic_cast具有「已知」繼承的模板類

// A bunch of classes exist which inherit from Base already. 
class Base{}; 
class Base2 : public Base {}; 
class BaseN : public Base {}; 

// Some new classes can inherit from any Base-derived class, 
// but also have special attributes (i.e. function "f"). 
template<typename T = Base> 
class Derived : public T 
{ 
    static_assert(std::is_base_of<Base, T>::value, 
     "Class must inherit from a type derived from Base.") 

    public: 
     void f(); 
}; 

// 
// Now process a collection of Base pointers. 
// 

std::vector<Base*> objects; 

// The vector may contain classes that are not "Derived". 
// I only care about the ones that are. 
// I want the cast here to return non-null for Derived<Base>, 
// Derived<Base2>, Derived<BaseN>, but null for Base, Base2, etc. 

// This will be Null, Good. 
objects.push_back(new Base) 
auto dcast0 = dynamic_cast<Derived<Base>*>(objects[0]); 

// This will be Non Null, Good. 
objects.push_back(new Derived<Base>); 
auto dcast1 = dynamic_cast<Derived<Base>*>(objects[1]); 

// This will be Null, BAD! HELP! 
objects.push_back(new Derived<Base2>); 
auto dcast2 = dynamic_cast<Derived<Base>*>(objects[2]); 
+3

派生!=派生。他們完全不同的類型,所以dcast2被正確設置爲空。解決這個問題的一種方法是讓Derived從另一個類繼承,讓我們說DerivedBase,然後動態地轉換爲它。 – Creris 2015-04-01 19:48:26

+0

你有兩種不同的概念混合在一起:運行時多態性和編譯時多態性。您可以按照Creris的建議或考慮重構您的代碼以避免比較不同的模板類型 – 2015-04-01 21:03:32

+0

派生的和派生的並非完全不同的類型,因爲它們都最終從Base繼承。也就是說,我可以成功將他們中的任何一個投射到基地。我並不是認爲這些演員是錯的,只是從一些可能的解決方案中展示了我所期望的。事實上,這是編譯時保證的混合,它們都是從Base繼承的,並且都具有由Derived定義的相同接口,我希望在運行時利用它。使用建議的DerivedBase是一個簡單的解決方案,最終解決了我想要的90%。 – DiB 2015-04-02 11:49:49

回答

1

如建議在評論Creris',你需要一個非模板基類是通用於所有的Derived<>模板類。另外,對Base本身的繼承應該是虛擬的,這樣當Derived<>被實例化時,只有一個Base實例。

struct Base { virtual ~Base() {} }; 
struct Base2 : virtual Base {}; 

struct DerivedBase : virtual Base {}; 

template <typename BASE = Base> 
struct Derived : DerivedBase, BASE {}; 

    Base *b = new Derived<Base2>; 
    assert(dynamic_cast<DerivedBase *>(b)); 
+0

我希望有人有巫術,但回到基礎知識,讓事情聯繫起來。感謝理智檢查! – DiB 2015-04-01 21:25:15