У меня есть класс, который адаптирует std::vector для моделирования контейнера объектов, специфичных для домена. Я хочу выставить большую часть API std::vector пользователю, чтобы он/она мог использовать знакомые методы (размер, прозрачность, at и т.д.) И стандартные алгоритмы на контейнере. Это, кажется, повторяющийся образец для меня в моих проектах:
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)
};
Я знаю о практике предпочтения композиции в наследовании при повторном использовании класса для реализации - но там должен быть предел! Если бы мне было делегировать все на std::vector, было бы (по моему счету) 32 функции пересылки!
Итак, мои вопросы... Неужели так сложно наследовать реализацию в таких случаях? Каковы риски? Есть ли более безопасный способ, которым я могу реализовать это, без большого набора текста? Я еретик для использования наследования реализации?:)
Edit:
Как ясно, что пользователь не должен использовать MyContainer с помощью std::vector < > pointer:
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
Библиотеки boost, похоже, все время делают это.
Изменить 2:
Одним из предложений было использование бесплатных функций. Я покажу его здесь как псевдокод:
typedef std::vector<MyObject> MyCollection;
void specialCollectionInitializer(MyCollection& c, arguments...);
result specialCollectionFunction(const MyCollection& c);
etc...
Еще один способ сделать это:
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.
}