2011-04-25 12 views
7

que tienen una jerarquía de clases como esto:C++ Resumen de clases como std :: mapa de teclado

struct Vehicle { 
    virtual string model() = 0; // abstract 
    ... 
} 
struct Car : public Vehicle {...} 
struct Truck : public Vehicle {...} 

necesito para mantener una std::map con alguna información que he adquirido sobre algunas Vehicle casos:

std::map<Vehicle, double> prices; 

sin embargo, me sale el siguiente 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() 

lo que no puede utilizar un cl abstracta culo como una clave std::map. Por lo que puedo decir, esto se debe a que los mapas copian sus claves (a través de copy-constructor u operador de asignación) y esto implicaría crear una instancia de una clase abstracta (Vehicle). Además, incluso si pudieras, seríamos presa de object slicing de todos modos.

¿Qué debo hacer?

Parece que no puedo utilizar punteros porque puede haber copias separadas de manera lógica idéntica Car s o Truck s. (Es decir, dos Car objetos instanciados por separado, pero que representan el mismo coche y operator== vuelve verdad. Necesito a éstos se asignan a un mismo objeto en el std::map.)

+0

por qué no dar '' Vehicle' un miembro con mas de? O use 'map ' para relacionar el nombre del modelo con el precio? – Beta

+0

@Beta Supongamos que se trata de una búsqueda determinada (por ejemplo, en un área geográfica específica). Además, eso no resuelve el problema de sincronización de copias a nivel de bits; si tiene dos instancias de 'Car', solo una obtendría el precio. –

+0

Los autos reales resuelven esto al tener un número de registro y un número de serie de fabricación exclusivo. –

Respuesta

10
  1. Necesita utilizar punteros a Vehicle.

  2. operator== no es utilizado por el std::map sino un comparar funtor que es el tercer parámetro de la std::map. Por defecto es std::less.Es necesario implementar su propio funtor comparar a trabajar con Vehicle:

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

y luego usarlo:

std::map<Vehicle *, double, less_vehicle> 
1

que necesitará utilizar punteros, y pasar un parámetro de plantilla para especificar el tipo de objeto que realizará la comparación (y cuando crea el mapa, pase un objeto de ese tipo para hacer las comparaciones).

Para su comparación, querrá desreferenciar los punteros y comparar los objetos a los que apuntan. También tenga en cuenta, sin embargo, que para que esto tenga éxito tendrá que definir algún tipo de comparación entre un automóvil y un camión. No necesariamente tiene que ser particularmente significativo, pero tiene que ser coherente y transitivo (la terminología oficial es que debe definir un "orden débil estricto").

+0

Gracias Jerry. Esto significa que necesito contar las clases aparte - ¿es la única manera de hacer esto RTTI? –

+0

@Adam, necesitará RTTI de alguna forma, de lo contrario las clases necesitarán conocerse entre sí para implementar el envío doble. – Begemoth

1

No puede usar un ABC como clave, porque tener una instancia de un ABC no tiene sentido.

Con la línea std::map<Vehicle, double> prices; que estás diciendo, "hacer un mapa con Vehicle casos como llaves". Como no puede tener instancias de Vehicle (ya que es puramente virtual), tampoco puede tenerlas como claves para su mapa.

No es algo que haya intentado antes, pero creo que usando un asignador personalizado con el map puede usar punteros Vehicle con comprobaciones de puntos lógicamente idénticos.

Cuestiones relacionadas