C ++抽象类作为std :: map键

时间:2011-04-25 05:10:02

标签: c++ stl map polymorphism abstract-class

我有这样的类层次结构:

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()

因此,您不能将抽象类用作std::map键。据我所知,这是因为地图复制了他们的密钥(通过复制构造函数或赋值运算符),这意味着实例化一个抽象类(Vehicle)。即使你可以,我们也会成为object slicing的牺牲品。

我该怎么办?

似乎我无法使用指针,因为可能存在逻辑上相同的CarTruck s的单独副本。 (即两个Car个对象分别实例化,但代表同一辆汽车而operator==返回true。我需要这些对象映射到std::map中的同一个对象。)

3 个答案:

答案 0 :(得分:10)

  1. 您需要使用指向Vehicle

  2. 的指针
  3. 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 { ... }
     };
    
  4. 然后使用它:

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

答案 1 :(得分:1)

您需要使用指针,并传递一个模板参数来指定将执行比较的对象类型(当您创建地图时,传递该类型的对象进行比较)。

为了进行比较,您需要取消引用指针并比较它们指向的对象。但是请注意,为了成功,您需要在汽车和卡车之间定义某种比较。它不一定非常有意义,但它必须是一致的和可传递的(官方术语是它必须定义“严格的弱排序”)。

答案 2 :(得分:1)

你不能使用ABC作为关键,因为拥有ABC的实例是没有意义的。

使用行std::map<Vehicle, double> prices;,您说“制作一张以Vehicle 实例为按键的地图”。由于您不能拥有Vehicle的实例(因为它是纯虚拟的),因此您不能将它们作为地图的键。

这不是我以前讨论过的东西,但我相信使用map的自定义分配器,您可以使用Vehicle指针检查逻辑上相同的指针。