2010-09-21 6 views
0

Я хотел бы написать «универсальный» класс, представляющий общие указатели хранения контейнера. Должен ли я использовать публичное наследование или сдерживание?Дизайн шаблона контейнера-указателя

template <class T> 
class List : public std::vector <T *> 
{ 
//... 
} 

Или

template <class T> 
class List 
{ 
private: 
    std::vector <T *> items; 
//... 
} 

Может некоторые проблемы возникают с абстрактными классами (т.е. виртуальный деструктор)?

Если ни одно из предложений не подходит, какой дизайн следует использовать (и вы могли бы включить короткий пример)?

+0

Его никто не назвал вектором списка. Когда вы говорите список, мы ожидаем определенные внутренние поведенческие модели. Вектор не обеспечивает эти поведения.Например, вставляя в середину списка, я ожидал бы постоянного времени (это не верно для вектора). –

+0

Взгляните на boost :: ptr_list, он должен делать то, что вы хотите. –

+0

@ Мартин: Он не думает о std :: list; другие языки/среды используют «список», где C++ использует «вектор». – 2010-09-21 22:22:31

ответ

2

Как насчет:

typedef std::vector<boost::shared_ptr<T> > List; 

То есть, я думаю, что лучше использовать управляющий указатель ресурса в регулярных контейнерных классов, чем изобретать каждый из классов контейнеров для добавления возможности управления ресурсами.

+0

Почему вы думаете, что это лучше? – 2010-09-21 22:10:16

+0

Но, на мой взгляд, такой солетон будет медленным. Мне нужна высокая производительность, которая не может быть предоставлена ​​shared_ptrs ... – Ian

+0

@Roger: Потому что вы правильно управляете ресурсами в одном месте (класс указателя), и вы можете использовать его в любом произвольном контейнере с этого момента. И когда вы получаете элемент из контейнера, вы получаете его с помощью умного указателя, который будет хорошо работать с общим управлением этим ресурсом. Использование основных указателей на C++ в большинстве случаев должно быть обескуражено. –

3

Это уже сделано для Вас с Boost's pointer containers.

Мне не нравится boost, поэтому я бы хотел использовать только C++ 0x00 standard :-).
  — Ian (comment)

Если вы все еще хотите, чтобы заново изобрести эти классы, обратите внимание на дизайнерские решения, которые они сделали. В частности, они не наследуются от других контейнеров, как это делает ваш первый код.

На самом деле, просто скопируйте код прямо из Boost. Это библиотека только для заголовков и должна быть прямой (т. Е. Несколько обходных решений для конкретной реализации). Boost's license очень либеральна, даже не требует упоминания Boost при распространении скомпилированных программ.

0

private Наследование - общая тактика для создания классов, которые реализуются в терминах другого. Код, который использует класс, не может сказать, что производный класс получен из частной базы, поэтому вы не окажетесь в ситуациях, которые обычно требуют виртуального деструктора.

Используйте команду using для импорта элементов из частной базы в производный класс. Например:

template<class T> 
class List: 
private std::vector<T> 
{ 
public: 
    using std::vector<T>::operator[]; 
    using std::vector<T>::size; 
}; 

Это немного грубо, но это дает вам некоторую гибкость. Вы можете начать с использования частного наследования, и это экономит вас при наборе текста по сравнению с написанием функций пересылки, но вы по-прежнему можете писать альтернативные варианты реализации по требованию. И тогда, если/когда это станет неуместным, вы можете изменить стиль реализации - возможно, например, в качестве члена есть vector, например, или, может быть, сделать все вручную без необходимости знать, что код клиента не потребуется изменять ,

Это идеальное решение для ситуаций, когда вы уверены, что в конечном итоге вам понадобится нестандартный тип контейнера, но у вас есть существующий тип контейнера, который в настоящее время больше подходит для счета. И это лучшее среднесрочное решение, чем typedef, потому что нет никакого риска для кода клиента случайно (или по назначению ...), используя два типа взаимозаменяемо.

+0

Обоснование для -1 с оценено;) – 2010-09-21 22:26:27

+0

Я не вижу причины ниспровергать либо (и у меня нет голосов за день, а завтра). Это хорошая стратегия реализации, хотя это конкретный случай имеет [лучший ответ] (http://stackoverflow.com/questions/3764836/design-of-pointer-container-template/3764877#3764877). ;) – 2010-09-21 22:30:54

+0

@Steve: Частное наследование - это инкапсуляция. – 2010-09-21 22:31:29

Смежные вопросы