我有这样的类层次结构:
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的牺牲品。
我该怎么办?
似乎我无法使用指针,因为可能存在逻辑上相同的Car
或Truck
s的单独副本。 (即两个Car
个对象分别实例化,但代表同一辆汽车而operator==
返回true。我需要这些对象映射到std::map
中的同一个对象。)
答案 0 :(得分:10)
您需要使用指向Vehicle
。
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 :(得分:1)
您需要使用指针,并传递一个模板参数来指定将执行比较的对象类型(当您创建地图时,传递该类型的对象进行比较)。
为了进行比较,您需要取消引用指针并比较它们指向的对象。但是请注意,为了成功,您需要在汽车和卡车之间定义某种比较。它不一定非常有意义,但它必须是一致的和可传递的(官方术语是它必须定义“严格的弱排序”)。
答案 2 :(得分:1)
你不能使用ABC作为关键,因为拥有ABC的实例是没有意义的。
使用行std::map<Vehicle, double> prices;
,您说“制作一张以Vehicle
实例为按键的地图”。由于您不能拥有Vehicle
的实例(因为它是纯虚拟的),因此您不能将它们作为地图的键。
这不是我以前讨论过的东西,但我相信使用map
的自定义分配器,您可以使用Vehicle
指针检查逻辑上相同的指针。