Tengo una clase que adapta std :: vector para modelar un contenedor de objetos específicos del dominio. Quiero exponer la mayor parte de la API std :: vector al usuario, para que pueda usar métodos familiares (tamaño, claro, at, etc.) y algoritmos estándar en el contenedor. Este parece ser un patrón recurrente para mí en mis diseños:
class MyContainer : public std::vector<MyObject>
{
public:
// Redeclare all container traits: value_type, iterator, etc...
// Domain-specific constructors
// (more useful to the user than std::vector ones...)
// Add a few domain-specific helper methods...
// Perhaps modify or hide a few methods (domain-related)
};
Soy consciente de la práctica de preferir la composición a la herencia cuando se reutiliza una clase para la implementación, ¡pero debe haber un límite! Si tuviera que delegar todo en std :: vector, ¡habría (según mi cuenta) 32 funciones de reenvío!
Entonces, mis preguntas son ... ¿Es realmente tan malo heredar la implementación en tales casos? ¿Cuáles son los riesgos? ¿Existe una forma más segura de implementar esto sin tener que escribir tanto? ¿Soy un hereje por usar la herencia de implementación? :)
Editar:
¿Qué hay de dejar en claro que el usuario no debe usar MyContainer a través de un puntero std :: vector <>:
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
Las bibliotecas de impulso parecen hacer estas cosas todo el tiempo.
Edición 2:
Una de las sugerencias fue utilizar funciones gratuitas. Lo mostraré aquí como pseudocódigo:
typedef std::vector<MyObject> MyCollection;
void specialCollectionInitializer(MyCollection& c, arguments...);
result specialCollectionFunction(const MyCollection& c);
etc...
Una forma más OO de hacerlo:
typedef std::vector<MyObject> MyCollection;
class MyCollectionWrapper
{
public:
// Constructor
MyCollectionWrapper(arguments...) {construct coll_}
// Access collection directly
MyCollection& collection() {return coll_;}
const MyCollection& collection() const {return coll_;}
// Special domain-related methods
result mySpecialMethod(arguments...);
private:
MyCollection coll_;
// Other domain-specific member variables used
// in conjunction with the collection.
}