2012-06-19 15 views
6

que tengo una clase como la siguiente:Permitir el acceso a los objetos contenedor en C++

class Foo { 
private: 
    std::map<std::string, Bar*> bars_by_name; 
    std::map<std::string, Baz*> bazs_by_name; 
}; 

Ahora me gustaría para permitir al usuario acceder a las dos colecciones, pero ocultar el detalle de implementación que estoy almacenando el objetos en std :: maps. En cambio, me gustaría tener funciones de miembros que devuelvan, p. const iterators para las colecciones y posiblemente incluso un iterador personalizado que devuelve objetos de ambas colecciones, ya que Bar y Baz pertenecen a la misma jerarquía de clases. Teniendo en cuenta el estilo, ¿cuál sería la forma correcta de hacerlo en C++? En Java, probablemente establezca el tipo de retorno del método en Iterable o ajuste la colección en una colección no modificable.

+1

Si utiliza algo como ['any_iterator'] (http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html), puede ocultar el tipo subyacente sin filtrar detalles. También puede usar algo como transform_iterator o zip_iterator de Boost como intermediario sin que los usos sean más acertados. – Flexo

Respuesta

1

Puede pasar los iteradores de la colección como propios.

class Foo { 
    private: 
    typedef std::map<std::string, Bar*> BarContainer; 
    typedef std::map<std::string, Baz*> BazContainer; 
    public: 
    typedef BarContainer::const_iterator ConstBarIterator; 
    ConstBarIterator beginBars() { return bars_by_name.cbegin(); } 
    ConstBarIterator endBars() { return bars_by_name.cend(); } 
    typedef BazContainer::const_iterator ConstBazIterator; 
    ConstBazIterator beginBazs() { return bazs_by_name.cbegin(); } 
    ConstBazIterator endBazs() { return bazs_by_name.cend(); } 

    private: 
    BarContainer bars_by_name; 
    BazContainer bazs_by_name; 
}; 

Esto le ahorra el trabajo de implementar su propio iterador, pero te deja la flexibilidad de cambiar sus tipos de contenedores más tarde y sólo requiere que llaman recompilar.

No resuelve el problema de iterarlos juntos.

+0

Gracias. Probé algo con los iteradores de Boost, pero no pude hacer que funcionaran, así que decidí hacer algo más primero. También encontré esta biblioteca, pero parece haber sido pre alfa durante más de diez años: http://www.zib.de/weiser/vtl/ – tsnorri

1

crear una interfaz que oculta los detalles:

class Foo { 
    public: 
     void AddBar(std::string name, Bar*); 
     void RemoveBar(std::string name); 

     Bar* GetBar(std::string name); 
     Bar* GetBar(std::string name) const; 

     void AddBaz(std::string name, Baz*); 
     void RemoveBaz(std::string name); 

     Baz* GetBaz(std::string name); 
     Baz* GetBaz(std::string name) const; 

    private: 
     std::map<std::string, Bar*> bars_by_name; 
     std::map<std::string, Baz*> bazs_by_name; 
}; 

Para todo el usuario sabe, usted podría ser ellas almacenando en un std :: par dentro de una lista, dentro de un vector, o incluso la utilización de matrices paralelas. ..cualquier cosa en realidad.

EDIT:

El hecho de que usted está almacenando en un mapa, pero desea que el usuario para iterar sobre los olores de contenedores subyacentes de un diseño de mala/incorrecta. O solo les permite el acceso individual como se indicó anteriormente o crea métodos que lo harán por ellos.

+0

El OP está buscando la forma de iterar sobre los contenidos ... –

+0

Además de lo que señaló Oli, exponer iteradores no tiene que revelar el tipo subyacente. Los iteradores podrían ser abstractos, por ejemplo, como el any_iterator señalado anteriormente. – stinky472

Cuestiones relacionadas