2012-07-05 49 views
2

我有兩個類,繼承相同的抽象基類:如何設計我的課程?

class base 
{ virtual void something() = 0; }; 

class a : public base 
{ 
    void something(); 
}; 

class b : public base 
{ 
    void something(); 

    // This is what I want: a list where I can store values of type a 
    // and of type b 
    // std::list<a & b> objs; 
}; 

我可以使用原始/智能指針(list<base*> obj_ptrs)的名單,但如何使用這個名單?

b b_obj; 
b_obj.obj_ptrs.push_back(new a()); 

// Who have to delete this pointer? Who use the class or who design 
// the class in the object destructor? 

// The following is valid for c++11 
auto p = b_obj.obj_ptrs.back(); 
// But if i'm using c++03? 

我想是誰使用的類必須這樣做的可能性:

a a_obj; 
b b_obj; 

b_obj.obj_ptrs.push_back(a); 
b_obj.obj_ptrs.push_back(b); 

如何有我設計我的類來完成這項工作?

回答

4

我可以使用原始/智能指針(list<base*> obj_ptrs)的名單,但如何使用這個名單?

你會多態調用虛函數,或在特殊情況下,使用dynamic_cast指針類型轉換爲a*b*與它們進行交互。

誰必須刪除這個指針?

您必須決定所有權方案。一種方法是在列表中存儲智能指針(通常爲unique_ptr,或者在特殊情況下可能爲shared_ptr),然後在從列表中刪除時它們將自動刪除。另一種方法是與列表分開管理對象,並將原始指針放入列表中。

// The following is valid for c++11 
auto p = b_obj.obj_ptrs.back(); 
// But if i'm using c++03? 

這相當於base * p = b_obj.obj_ptrs.back();auto不會神奇地給出動態指針類型,它只是靜態指針類型的快捷方式。

我怎麼設計我的課程來完成這項工作? (存儲不同類型的對象)

存儲不同類型的對象可以使用識別聯合來完成 - 基本上,有一些額外的元數據並集以跟蹤哪些聯盟成員處於活動狀態。這些在C++中實現相當棘手,但您可以使用Boost.VariantBoost.Any。這具有以下優點:您不需要公共基類或存儲類型的任何其他支持;任何一組(非抽象)類型都可以使用。

+0

當我想要回最後一個對象時,我怎麼知道我是否必須編寫'a * aPtr = dynamic_cast(b_obj.obj_ptrs.back());'或'b * bPtr = dynamic_cast (b_obj.obj_ptrs.back ());',即我怎麼知道我的對象在列表中的類型是什麼? – Nick 2012-07-05 20:36:32

+0

@Nick:你不知道類型,這就是爲什麼通常使用虛函數來完成多態的原因。你必須嘗試每種類型:'if(a * p = dynamic_cast (b_obj.obj_ptrs.back()){/ *它是一個「a」* /}'。正如我在答案中所說的那樣,情況,當你不能讓虛擬功能爲你工作。 – 2012-07-05 22:54:55

0

std::list<a & b> objs; 不正確。我想你的意思std::list<base*> objsstd::list<base&> objs 所以,加元也

a a_obj; 
b b_obj; 
b_obj.objs.push_back(&a_obj); 
b_obj.objs.push_back(&b_obj); 
base* p = b_obj.objs.back(); 

或改用指針引用。

+4

您不能將引用存儲在容器中。 – 2012-07-05 12:47:54

+0

我知道它不會編譯,只是一個例子。請更多關注我的問題。 – Nick 2012-07-05 12:49:32

+0

@CatPlusPlus是的,我忘記了。謝謝。 – ForEveR 2012-07-05 12:52:14

2

使用共享指針列表是非常安全的,並很容易:

std::list<std::shared_ptr<base>> the_list; 

如果你繼續爲您的規則,你添加任何對象將與new分配,shared_ptr會照顧刪除你的時候該對象不再被引用計數。 (shared_ptr實現引用計數)

std::shared_ptr<a> my_a(new a); 
std::shared_ptr<b> my_b(new b); 

the_list.push_back(my_a); 
the_list.push_back(my_b); 

std::shared_ptr<base> my_object = the_list.back(); 
0

如果你真的只在乎類型ab存儲值和這些類型才考慮有一個std::list<a>和一個std::list<b>內部和兩個ab超載適當的公共構件,其轉發到適當的列表(例如,使得b obj; obj.push_back(value);將是優選的用法)。

只要您不關心ab對象之間插入的相對順序,您不需要擔心所有權,也不需要支付與使用動態分配相比的動態分配成本。 std::unique_ptr<base>並表示最接近你想要的。