2015-05-04 68 views
1

我有一個基類,它包含一個成員變量std :: unique_ptr < Base> next。我有幾個派生類的基地。實例化多態成員變量是合適的類型

我有一個非虛函數Base :: grow(),接下來要初始化。接下來將總是指向調用對象類型的對象增長。

接下來是正確的類型,通過Base :: grow()內的虛函數調用來保證。

爲每個派生類創建一個虛擬函數很麻煩並且容易出錯,因此我的問題是:我可以更簡單地做到這一點嗎?

我目前的工作極少例子是這樣的:

#include <iostream> 
#include <memory> 

class Base{ 
    public: 
    static const unsigned SIZE = 3; 
    std::unique_ptr<Base> next; 
    void grow(unsigned index){ 
     if (index < SIZE){ 
     print(); 
     next = get_new(); 
     next.get()->grow(index + 1); 
     } 
    } 

    virtual std::unique_ptr<Base> get_new(){ 
     return std::unique_ptr<Base>(new Base()); 
     //return std::move(std::unique_ptr<Base>(new Base())); (move not nec. see comments) 
    } 

    virtual void print(){ 
     std::cout << "a Base "; 
    } 
}; 

class Derived: public Base{ 
    public: 
    virtual void print(){ 
     std::cout << "a Derived "; 
    } 
    virtual std::unique_ptr<Base> get_new(){ 
     return std::unique_ptr<Base>(new Derived()); 
    } 
}; 

int main(){ 
    std::unique_ptr<Base> b; 
    b = std::unique_ptr<Base> (new Base()); 
    b->grow(0); 

    std::unique_ptr<Base> c; 
    c = std::unique_ptr<Base> (new Derived()); 
    c->grow(0); 
} 

輸出是正確的:一個基地一個基地一個基地一個導出的導出派生

總結:我想一個解決方案,消除繁瑣的get_new,我希望Base :: grow根據調用對象的類型確定要創建的類型。我考慮過使用decltype,但沒有成功。

代碼段與嘗試在運行時確定類型:以上

typedef std::remove_reference<decltype(*this)>::type DynamicBase; 
next = std::unique_ptr<DynamicBase>(new DynamicBase()); 

DYNAMICBASE總是確定爲基地,即使this是指向派生

+2

C++沒有一個可靠的方法來獲得「通話對象」的類型在運行時(除非「調用對象」你的意思是'this' - - 你可以通過RTTI獲得有限的*信息),即使這樣你也需要一些反射能力來創建一個新類型的對象。總之,沒有答案滿足您的具體要求,因爲它不能在C++中完成。如果你對他們開放,可能會有其他選擇。 – cdhowie

+2

你不需要'移動'std :: unique_ptr (新的Base())'表達式,它已經是一個右值。 – aschepler

+0

@cdhowie我認爲這個評論應該是一個答案。 – Walter

回答

2

你想要什麼是不可能的:您至少需要一個虛擬函數調用,即在每個派生的虛擬方法中重寫。例如,考慮派生類在另一個編譯單元中定義的情況。如果不使用多態性,基類的代碼應該如何獲得未知類型的新派生對象?

+0

有意義的是get_new需要在每個類中重寫。但是由於虛擬函數全部基本相同,如果有一些類似於模板的方法來自動生成它們,那將會很不錯。 – newling

相關問題