2012-10-24 122 views
9

如果我有一個基類,其中只有虛擬方法和來自 的2個派生類,並且實現了這些虛方法。指向基類數組的指針,使用派生類填充

我如何:

// causes C2259 
BaseClass* base = new BaseClass[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

或:

// causes "base is being used without being initialized" 
BaseClass* base; 
// causes CC59 again 
BaseClass* base = new BaseClass; 

base[0] = FirstDerivedClass(); 
base[1] = SecondDerivedClass(); 

(或類似的東西)

...所以,我可以通過DerivedClass訪問BaseClass小號方法, 但通過指針和指針是一個數組DerivedClass s?

回答

8

你的陣列是錯誤的類型的:它存儲BaseClass對象實例而不是指針給他們。由於BaseClass似乎是抽象的,編譯器會抱怨它不能默認構建實例來填充你的數組。

即使BaseClass不是抽象的,在C++中使用多態數組是一個big no-no,所以你應該在任何情況下做不同的事情。

修復此由代碼改變爲:

BaseClass** base = new BaseClass*[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

儘管如此,大多數情況下它是優選使用std::vector而不是純陣列和智能指針(如std::shared_ptr)代替啞指針。使用這些工具而不是手動編寫代碼將以極低的運行時間成本透明地處理大量問題。如果沒有的話,你會得到內存泄漏

BaseClass* base = new BaseClass[2]; 

+1

這個被稱爲「對象分片」的問題並不特定於數組 - 它隨時都會通過值*將派生類分配給基類*。例如。 'BaseClass b; b = FirstDerivedClass();'是可編譯的C++,但仍然默默地破解(最好你可能會得到一個編譯器警告)。 –

+0

鏈接似乎被移動。 – user6003859

+1

@ user6003859我更新了它,感謝您的發現! – Jon

3

這是C++中使用std::vector代替簡單的數組:

std::vector<BaseClass*> base; 
base.push_back(new FirstDerivedClass()); 
base.push_back(new SecondDerivedClass()); 

作爲Kerrek SB注意到最安全的方法是使用std::unique_ptr

std::vector<std::unique_ptr<BaseClass> > base; 
base.push_back(std_unique_ptr<BaseClass>(new FirstDerivedClass())); 
base.push_back(std_unique_ptr<BaseClass>(new SecondDerivedClass())); 
+2

但如果我想要一個數組? – Deukalion

+1

什麼?速度?可靠性? –

+0

那麼:BaseClass * Base [2]; Base [0] = new FirstDerivedClass; Base [1] = new SecondDerivedClass; – Al2O3

2

如果您的BaseClass包含純虛方法,這將編譯失敗。

在C++中,這是通過使用std :: vector或std :: array以及某種智能指針來完成的。例如:

std::vector< std::shared_ptr<BaseClass> > arr(2); 
arr[0].reset(new FirstDerivedClass()); 
arr[1].reset(new SecondDerivedClass()); 
+0

OP代碼的一個更重要的問題是* object slicing *,它會以無聲方式破壞程序。 –

+0

@j_random_hacker這就是爲什麼我建議使用某種智能指針。存儲基本類型的對象(如果它沒有純函數)會導致切片 –

0

這是答案(從幾度夕陽紅)

BaseClass* Base[2]; 

Base[0] = new FirstDerivedClass; 
Base[1] = new SecondDerivedClass; 
+1

這與您的原始代碼嘗試做的事情*有很* *不同。這個數組在堆棧上分配,而最初它在堆上。 – Jon

+0

是的,我猜。現在該數組是一個指針,數組中有指針。 – Deukalion

0

定義一個指針數組,該指針類型是BaseClass的。 然後將派生類的指針指定給數組的元素。 就像:

BaseClass* base [2]; 
base[0] = new FirstDerivedClass; 
base[1] = new SecondDerivedClass; 
相關問題