我有一个这样的类层次结构:
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
)
-
您需要使用指向
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>
您需要使用指针,并传递一个模板实参来指定执行比较的对象类型(当您创建映射时,传递该类型的对象来进行比较)。
对于比较,您需要对指针解引用并比较它们所指向的对象。但是,还要注意,为了成功实现这一点,您需要在Car和Truck之间定义某种比较。它不一定要特别有意义,但它必须是一致的和可传递的(官方术语是它必须定义一个"严格弱排序")。
不能使用ABC作为键,因为拥有ABC的实例没有意义。
对于std::map<Vehicle, double> prices;
行,你说,"用Vehicle
实例作为键制作映射"。因为你不能有Vehicle
的实例(因为它是纯虚拟的),你也不能把它们作为映射的键。
这不是我以前涉足的东西,但我相信使用map
的自定义分配器,您可以使用Vehicle
指针检查逻辑上相同的点。