У мене є клас, який адаптує 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 функції пересилання!
Тож мої запитання: Чи справді так погано успадковувати реалізацію у таких випадках? Які ризики? Чи є більш безпечний спосіб я можу реалізувати це, не надто багато друкуючи? Я єретик для використання успадкування реалізації? :)
Редагувати:
А як щодо того, щоб дати зрозуміти, що користувач не повинен використовувати MyContainer через покажчик std :: vector <>:
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
Бібліотеки, що працюють над підвищенням, здається, постійно роблять це.
Редагувати 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.
}