C++抽象类作为 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
或 Truck
的单独副本。 (即两个 Car
对象分别实例化,但代表同一辆车,并且 operator==
返回 true。我需要将它们映射到 std 中的同一对象::地图
。)
I have a class hierarchy like this:
struct Vehicle {
virtual string model() = 0; // abstract
...
}
struct Car : public Vehicle {...}
struct Truck : public Vehicle {...}
I need to keep a std::map
with some information that I acquire about some Vehicle
instances:
std::map<Vehicle, double> prices;
However I get the following error:
/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()
So you can't use an abstract class as a std::map
key. As far as I can tell this is because maps copy their keys (via copy-constructor or assignment operator) and this would imply instantiating an abstract class (Vehicle
). Also even if you could, we'd fall prey to object slicing anyway.
What should I do?
It seems I can't use pointers because there might be separate copies of logically identical Car
s or Truck
s. (i.e. Two Car
objects instantiated separately, but which represent the same car and operator==
returns true. I need these to map to the same object in the std::map
.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要使用指向
Vehicle
的指针。operator==
不被std::map
使用,而是一个比较函子,它是std::map
的第三个参数>。默认情况下它是std::less
。您需要实现自己的比较函子才能与Vehicle
一起使用:然后使用它:
You need to use pointers to
Vehicle
.operator==
is not used by thestd::map
but a compare functor which is the third parameter of thestd::map
. By default it isstd::less
. You need to implement your own compare functor to work withVehicle
:And then use it:
您需要使用指针,并传递模板参数来指定将执行比较的对象类型(并且在创建映射时,传递该类型的对象来进行比较)。
为了进行比较,您需要取消引用指针并比较它们指向的对象。但还要注意,要成功,您需要定义汽车和卡车之间的某种比较。它不一定必须特别有意义,但它必须是一致的和传递的(官方术语是它必须定义“严格的弱排序”)。
You'll need to use pointers, and pass a template argument to specify the type of object that will carry out the comparison (and when you create the map, pass an object of that type to do the comparisons).
For your comparison, you'll want that to dereference the pointers and compare the objects they point at. Also note, however, that for this to succeed you'll need to define some sort of comparison between a Car and a Truck. It doesn't necessarily have to be particularly meaningful, but it does have to be consistent and transitive (the official terminology is that it must define a "strict weak ordering").
您不能使用 ABC 作为键,因为拥有 ABC 的实例没有意义。
使用
std::map行价格;
你是说,“用Vehicle
实例 作为键来制作地图”。由于您不能拥有Vehicle
实例(因为它是纯虚拟的),因此您也不能将它们作为地图的键。这不是我以前涉足过的东西,但我相信使用带有
map
的自定义分配器,您可以使用Vehicle
指针来检查逻辑上相同的指针。You cant use an ABC as a key, because having an instance of an ABC doesn't make sense.
With the line
std::map<Vehicle, double> prices;
you're saying, "make a map withVehicle
instances as keys". Since you can't have instances ofVehicle
(as it is pure virtual), you can't have them as keys to your map either.It's not something I've dabbled with before, but I believe using a custom allocator with the
map
you can useVehicle
pointers with checks for logically identical pointees.