抽象类作为std::map键



我有一个这样的类层次结构:

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)。而且,即使你可以,我们也会成为对象切片的牺牲品。

我该怎么办?

似乎我不能使用指针,因为可能有逻辑上相同的Car s或Truck s的单独副本(即两个Car对象分别实例化,但它们代表相同的汽车和operator==返回true。我需要这些映射到相同的对象在std::map)

  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>

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

对于比较,您需要对指针解引用并比较它们所指向的对象。但是,还要注意,为了成功实现这一点,您需要在Car和Truck之间定义某种比较。它不一定要特别有意义,但它必须是一致的和可传递的(官方术语是它必须定义一个"严格弱排序")。

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

对于std::map<Vehicle, double> prices;行,你说,"用Vehicle 实例作为键制作映射"。因为你不能有Vehicle的实例(因为它是纯虚拟的),你也不能把它们作为映射的键。

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

相关内容

最新更新