Рассмотрим следующий пример кода:с ++ проблема с полиморфизмом и векторы указателей
class Foo
{
};
class Bar : public Foo
{
};
class FooCollection
{
protected:
vector<shared_ptr<Foo> > d_foos;
};
class BarCollection : public FooCollection
{
public:
vector<shared_ptr<Bar> > &getBars()
{
// return d_foos won't do here...
}
};
У меня есть проблема, как это в моем текущем проекте. Клиентский код использует BarCollection
, который хранит указатели на Bars
в d_foos
, который объявлен в FooCollection
. Теперь я хотел бы показать коллекцию указателей на Bars для кода клиента. Я мог бы просто предоставить клиенту код доступа к вектору указателей к Foo
и передать их указателям на Bar
s в клиентском коде, но это кажется неправильным, так как клиент не должен знать о существовании Foo
.
Я также могу определить член get()
, который извлекает объекты из d_foos
и бросает их, но это кажется довольно неуклюжим. Предпочтительно, я хотел бы просто вернуть d_foos как vector<shared_ptr<Bar> > &
, но я не могу этого сделать.
Возможно также, что мой дизайн просто неправильный. Это, казалось, наиболее естественное решение, поскольку, как Bar
является специализацией Foo
и BarCollection
является специализацией FooCollection
и они имеют общие функциональные возможности.
Не могли бы вы предложить прекрасные решения для внедрения getBars
в BarCollection
или лучше вариантов дизайна?
Edit:
Оказывается, мой дизайн был плохо на самом деле. BarCollection не является FooCollection, несмотря на то, что он требует всех функциональных возможностей FooCollection. Мое текущее решение, основанное на ответах ниже - который намного чище - теперь:
class Foo
{
};
class Bar : public Foo
{
};
template<class T>
class Collection
{
vector<shared_ptr<T> > d_items;
};
typedef Collection<Foo> FooCollection;
class BarCollection : public Collection<Bar>
{
// Additional stuff here.
};
Спасибо за все отличные предложения и примеры!
Я опубликовал решение ... в основном для полноты, хотя он включает в себя 'reinterpret_cast'. Я настоятельно призываю вас рассмотреть альтернативы рефакторинга. В частности, вы перепутали отношения IS-A, введенные путем наследования с повторным использованием кода. Кроме того, вы не хотите иметь 'getBars'. Раскрытие ваших личных частей считается эксгибиционизмом и наказуемым законом. –
@Matthieu: Я добавил свое реорганизованное текущее решение проблемы. Благодаря! –