2013-01-17 26 views
0

這是問題所在,我有一個指針的向量,以充滿派生的對象,像這樣一個抽象基類:如何在基類的向量中返回派生對象的副本?

class AbstractBase { /* ... */ }; 

clase Derived1 : public AbstractBase { 
    Derived1() { } 
    Derived1(const AbstractBase& abc) { /* ... */ } 
}; 

/* ... */ 

vector< AbstratcBase* > lThingies; 

const AbstractBase& getThingie(int pos) { 
    return *lThingies[pos]; 
} 

而且得到我使用派生類「的拷貝構造函數」像這樣的元素的副本:

Derived1 d1 = getThingie(2); 

但問題是,我不喜歡這樣的:有沒有辦法迫使這個「拷貝構造函數」建設一流「derived42」時的執行情況,即使你還記得它很容易讓它出錯(比如使它成爲遞歸調用,發生在我身上)。

我的問題是:有沒有更好的方法來做到這一點?怎麼樣?

更新:
其中之一,我正在尋找解決方案的「不成文」的要求是讓副本衍生對象作爲一個局部變量,所以我不要忘了刪除它。

更多信息:
有許多的lThingies和在運行時,我可以告訴大傢什麼都包含在(derived1,Derived2的,等等)派生的對象,而不是在編譯時。

+1

多態性和複製語義不能很好地結合在一起。不要製作顯式派生類型的副本。 –

+2

你有沒有聽說過[virtual constructor idiom](http://www.parashift.com/c++-faq/virtual-ctors.html)? – Fiktik

+0

我聽說過虛擬構造函數的習慣用法,但我不想在完成它時刪除對象。 – Fabi1816

回答

0

您知道嗎getThingie會返回一個Derived1?如果您知道這一點,可能應將Derived1的返回類型和std::vector中的存儲更改爲Derived1而不是AbstractBase

假設上述不工作,你可以做一個Derived1 bob = dynamic_cast<Derived1&>(getThingie(...));,它不運行時檢查啄是Derived1以上派生的實例,如果它確實是這樣投 - 如果不是,它拋出一個例外。

如果您不想打擾運行時間檢查,因爲您確信它是Derived1,只需使用Derived1 bob = static_cast<Derived1&>(getThingy(...));即可。

但是,處理具有繼承層次結構的類的實際實例是非常有問題的。有很多很多事情可能會出錯。

+0

你能舉出一個可以出錯的例子嗎? – Fabi1816

+0

@Fabi1816切片就是一個例子。 – Yakk

+0

即使存在潛在的問題,這也解決了我迄今爲止的所有問題 – Fabi1816

4

您可以在AbstractBase中製作純虛擬clone函數,該函數返回AbstractBase指針,並覆蓋派生類中的clone


嚴格意見:

這有點粗暴和過時的做法。雖然(在我看來)。我建議重新設計,以免首先做到這一點。

爲了詳細說明虛擬構造函數用法的我的毛和過時的意見(我敢肯定,這將是有爭議的):

  • 要真正健壯/通用克隆將需要模板爲分配器,就像一些STL構造一樣。但是,它不可能。
  • 你什麼時候想要複製一個你不知道具體類型的對象?我質疑該用例的合法性。
+1

有意詳細說明「粗糙和過時」的位? –

+0

似乎更「正確」的方法,我只是不想「刪除」返回的指針。 – Fabi1816

+1

@ Fabi1816這就是智能指針('std :: shared_ptr'和'std :: unique_ptr')的用途。在現代代碼中沒有理由調用delete。假裝關鍵字不存在。 – David

0
class A 
{ 
    public: 
    virtual void toto() { std::cout << "Love Java" <<std::endl; } 
    virtual A&& Duplicate() { return std::move(A()); } 
}; 

class B : public A 
{ 
    public: 
    virtual void toto() { std::cout << "Love C++11" <<std::endl; } 
    virtual B&& Duplicate() { return std::move(B()); } 
}; 

int main() 
{ 
    A *a = new B();; 

    A&& b(a->Duplicate()); 

    a->toto(); 
    b.toto(); 
} 

在主創建堆棧A B不知道他的類型。 (用C++ 11中的右值引用)

相關問題