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

发布于 2024-11-02 21:52:19 字数 1555 浏览 1 评论 0原文

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

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

我应该怎么办?

看来我无法使用指针,因为可能存在逻辑上相同的 CarTruck 的单独副本。 (即两个 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 Cars or Trucks. (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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

挽你眉间 2024-11-09 21:52:19
  1. 您需要使用指向Vehicle的指针。

  2. operator== 不被 std::map 使用,而是一个比较函子,它是 std::map 的第三个参数>。默认情况下它是std::less。您需要实现自己的比较函子才能与 Vehicle 一起使用:

     struct less_vehicle: std::binary_function;
     {
       bool 运算符() (const 车辆 *a, const 车辆 *b) const { ... }
     };
    

然后使用它:

std::map<Vehicle *, double, less_vehicle>
  1. You need to use pointers to Vehicle.

  2. operator== is not used by the std::map but a compare functor which is the third parameter of the std::map. By default it is std::less. You need to implement your own compare functor to work with Vehicle:

     struct less_vehicle: std::binary_function<const Vehicle *, const Vehicle *, bool>
     {
       bool  operator() (const Vehicle *a, const Vehicle *b) const { ... }
     };
    

And then use it:

std::map<Vehicle *, double, less_vehicle>
没企图 2024-11-09 21:52:19

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

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

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").

小镇女孩 2024-11-09 21:52:19

您不能使用 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 with Vehicle instances as keys". Since you can't have instances of Vehicle (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 use Vehicle pointers with checks for logically identical pointees.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文