2011-04-25 76 views
7

我有一個類層次結構是這樣的:C++抽象類象std ::地圖鍵

struct Vehicle { 
    virtual string model() = 0; // abstract 
    ... 
} 
struct Car : public Vehicle {...} 
struct Truck : public Vehicle {...} 

我需要保持std::map與我獲得了一些Vehicle情況下的一些信息:

std::map<Vehicle, double> prices; 

但是我收到以下錯誤:

/usr/include/c++/4.2.1/bits/stl_pair.h: In instantiation of ‘std::pair<const Vehicle, double>’: 
/usr/include/c++/4.2.1/bits/stl_map.h:349: instantiated from ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = Vehicle, _Tp = double, _Compare = std::less<Vehicle>, _Alloc = std::allocator<std::pair<const Vehicle, double> >]’ 
test.cpp:10: instantiated from here 
/usr/include/c++/4.2.1/bits/stl_pair.h:73: error: cannot declare field ‘std::pair<const Vehicle, double>::first’ to be of abstract type ‘const Vehicle’ 
Model.hpp:28: note: because the following virtual functions are pure within ‘const Vehicle’: 
Model.hpp:32: note:  virtual string Vehicle::model() 

因此,您不能使用抽象cl屁股作爲std::map的關鍵。據我可以告訴這是因爲地圖複製他們的鍵(通過複製構造函數或賦值運算符),這意味着實例化抽象類(Vehicle)。同樣,即使你可以,我們仍然會墮入object slicing

我該怎麼辦?

看來我不能使用指針,因爲有可能是邏輯上相同的Car S或Truck S的單獨副本。 (即兩個Car對象單獨實例化,但它代表了同一輛車和operator==返回true。我需要這些映射到同一個對象在std::map。)

+0

爲什麼不給'Vehicle'一個'price'會員?或者使用'map '將模型名稱與價格關聯起來? – Beta 2011-04-25 05:17:16

+0

@Beta假設這是針對一個給定的搜索(比如說,在一個特定的地理區域)。此外,這並不解決位複製同步問題;如果你有兩個'Car'的實例,只有一個會得到價格。 – 2011-04-25 05:17:58

+0

真車通過註冊號碼和唯一的製造序列號解決此問題。 – 2011-04-25 05:21:47

回答

10
  1. 您需要使用指向Vehicle的指針。

  2. operator==不被std::map使用,而是比較函子,它是std::map的第三個參數。默認情況下它是std::less。您需要實現自己的比較仿函數與Vehicle工作:

    struct less_vehicle: std::binary_function<const Vehicle *, const Vehicle *, bool> 
    { 
        bool operator() (const Vehicle *a, const Vehicle *b) const { ... } 
    }; 
    

,然後使用它:

std::map<Vehicle *, double, less_vehicle> 
1

你需要使用指針,並通過一個模板參數指定將執行比較的對象的類型(以及創建地圖時,傳遞該類型的對象以進行比較)。

爲了便於比較,您需要取消引用指針並比較它們指向的對象。但是請注意,爲了取得成功,您需要定義汽車和卡車之間的某種比較。它不一定非常有意義,但它必須是一致的和傳遞的(官方術語是它必須定義一個「嚴格的弱秩序」)。

+0

謝謝傑瑞。這意味着我需要分開講課 - 是做RTTI的唯一方法嗎? – 2011-04-25 15:14:03

+0

@Adam,你需要某種形式的RTTI,否則這些類將需要了解彼此以實現雙重調度。 – Begemoth 2011-04-25 17:57:47

1

你不能使用ABC作爲關鍵,因爲擁有一個ABC的實例是沒有意義的。

隨着線std::map<Vehicle, double> prices;你是說,「與Vehicle實例作爲鍵的地圖」。由於你不能擁有Vehicle的實例(因爲它是純虛擬的),所以你不能將它們作爲映射的鍵。

這不是我曾經涉足的東西,但我相信使用map自定義分配器可以使用Vehicle指針檢查邏輯上相同的pointees。