2013-07-27 29 views
0

我知道這個問題已經被問了很多,我用google搜索,但是不能把所有東西放在一起。也許是因爲這是不可能的,我想要什麼?對象,繼承,dynamic_cast需要建議

struct Universe 
{ 
} 

struct Atom: Universe 
{ 
} 

struct Molecule: Universe 
{ 
} 

Universe U; 
Atom A; 
Molecule M; 
_atoms = vector<Universe*>(3); 
_atoms.push_back(&U); 
_atoms.push_back(dynamic_cast<Universe*>(&A)); 
_atoms.push_back(dynamic_cast<Universe*>(&M)); 

auto THIS_IS_ATOM = _atoms[1]; 

這個代碼是最有可能的錯誤在許多方面。但我的想法是像這樣存儲不同的派生結構,並稍後從數組或列表中訪問它們,而沒有任何dataloss或類被截斷。我想從數組中得到一些元素,比如_atoms [1],並且能夠知道這個結構是什麼類型(Universe或者Atom)和e.t.c。我應該如何在C++中正確地做到這一點?

回答

0

你的代碼有幾個問題。

  1. 宇宙需要一個虛擬析構函數。
  2. 您必須在堆上創建實例。
  3. 您正在使用錯誤的std :: vector構造函數。

下面是應該工作的解決方案:

struct Universe { 
    virtual ~Universe() {} // otherwise Atom and Molecule will not be deleted properly 
} 

struct Atom : Universe { 

} 

struct Molecule : Universe { 

} 

std::vector<Universe*> _atoms; // you don't need to pass anything in the constructor 
_atoms.reserve(3); // but if you want to make sure that the vector has exactly a capacity of 3, use this 

_atoms.push_back(new Universe()); 
_atoms.push_back(new Atom()); 
_atoms.push_back(new Molecule()); 

auto this_is_atom = _atoms[1]; // will actually be equivalent to 
Universe* this_is_atom = _atoms[1]; 

// finally you must delete all the instances which you created on the heap 
while (!_atoms.empty()) delete _atoms.back(), _atoms.pop_back(); 

附錄:如果您需要治療的載體非多態的對象,你可以將它們轉換爲適當類型的靜態澆鑄:

Atom* a = static_cast<Atom*>(_atoms[1]); 

編輯:不要使用原始指針的載體,最好是使用智能指針的載體代替,例如性病::的unique_ptr或std :: shared_ptr的,這取決於所有權語義你想模擬。

+1

你的'公共'關鍵字,它什麼也不做。 ('struct'默認爲'public')。你可能不應該建議人們創建一個'std :: vector'的原始指針 - 只需創建一個'std :: vector >'。 – Yakk

+0

@Yakk,感謝您提供默認情況下公開結構繼承的提示,我不知道這一點。據此編輯答案。關於智能指針,我原則上同意,但不想將看起來是初學者的OP與智能指針混淆。 +1指出這一點雖然。 –

+0

非常感謝大家,我從這個例子中學到了很多東西,並且證實了很多。 Yakk,關於unique_pointer的好點,我最好習慣隨時使用它們。 – user2426290