Каков наилучший способ иметь коллекцию экземпляров классов, производных от одного базового класса? - PullRequest
3 голосов
/ 13 марта 2012

У меня есть коллекция классов, полученных из общей базы. Мне нужна коллекция (вероятно, list), которая будет содержать экземпляры производных классов различных типов. Операции класса будут вызывать виртуальные методы для экземпляров в коллекции. Конечно, я не могу использовать list<Base>, потому что удержание базового класса по значению приведет к разрезу производных классов.

Очевидное решение - использовать list<Base*> и обернуть его в классе с помощью конструктора копирования, деструктора и так далее. Базовый класс будет иметь виртуальную функцию duplicate, которая перегружается в каждом производном классе, чтобы возвращать указатель на созданный при копировании новый экземпляр этого производного класса. Деструктор должен пройти список и delete каждый элемент.

Если есть способ Boost, это нормально. Я уже использую Boost. Мне кажется, что использование общих указателей Boost было бы лучшим способом. Это может привести к дополнительным расходам в управлении общим количеством ссылок, но это должно быть дешевле, чем выделение / копирование, требуемое в случае указателя. Однако это будет означать, что копии коллекции приведут к одним и тем же экземплярам, ​​а изменение одной копии изменит другую.

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

Есть ли другой способ?

1 Ответ

10 голосов
/ 13 марта 2012

Скажите привет Boost.PointerContainer . По умолчанию они предлагают семантику глубокого копирования при копировании контейнеров (однако, это можно настроить). Обратите внимание, что вам нужно реализовать бесплатный метод new_clone для вашего абстрактного базового класса в соответствующем пространстве имен.

Также, в качестве примечания, , пожалуйста, , используйте std::vector в качестве контейнера первого выбора.

Еще одно примечание: не оборачивайте container<Base*>, а скорее оберните Base*, как вы уже догадались, умный указатель. C ++ 11 предлагает unique_ptr, если вы не хотите совместно владеть. unique_ptr разрешает только перемещение , копировать нельзя.

...