2012-06-14 2 views
1

У меня есть класс Bar, который хранит объекты, полученные из BarItem:Лучший способ добавления копии объекта в контейнер

#include <list> 
#include <memory> 

class Bar { 
public: 
    typedef std::shared_ptr<BarItem> item_ptr; 

    void add_item(item_ptr item) { 
     items_.push_back(item); 
    } 

private: 
    std::list<item_ptr> items_; 
}; 

У меня есть еще один класс Note который является подклассом BarItem. В настоящее время, чтобы добавить копию Note объекта я делаю:

Bar my_bar; 
Note my_note; 

my_bar.add_item(Bar::item_ptr(new Note(my_note))); 

который немного некрасиво; Я хотел бы знать, есть ли лучший способ или способ автоматизировать это?

+0

какой-либо причине вы не делаете 'my_bar.add_item (Bar :: item_ptr (my_note));' –

+0

@Hans my_note является Примечание объект не является указателем на Примечание. –

ответ

1

Вы не можете фактически избежать копирования (в C++ 11 вы можете сделать это движение), но вы можете «автоматизировать» его, чтобы сохранить несколько нажатий клавиш, перегружая функцию add_item для каждого типа (что может быть ребенком BarItem).

template <class T> 
typedef enable_if<is_base_of<BarItem, T>::value,void>::type add_item(const T& item) { /* or T&& */ 
    items_.push_back(item_ptr(new T(item))); 
} 
+0

Могу ли я спросить, в чем преимущество добавления enable_if? Разве вы не получите ошибку компиляции, если 'T' не является подклассом' BarItem'? – Lerp

+0

@Rarge: Да, вы получите ошибку компиляции. Не было бы никакой разницы, например. 'Примечание', так что это может быть способ пойти. 'Enable_if' заставляет шаблонную перегрузку уходить с пути, когда' T' не является дочерним элементом 'BarItem', а не' shared_ptr ', но может быть преобразовано в него, например' shared_ptr '(если «Примечание» является дочерним элементом «BarItem»). Без SFINAE вы получите ошибку двусмысленности; с его помощью вы получите вызов своей оригинальной функции с конверсией. – jpalecek

1

Вы можете переместить эту уродливую часть в функции самого как:

template<typename ItemType> 
void add_item(ItemType item) //change the signature 
{ 
    items_.push_back(new ItemType(item)); //add the copy! 
} 

и называют его:

my_bar.add_item(my_note); 
0

Использование указателей в контейнерах является одним из способов уменьшения копирования объектов. Но то, как вы обрабатываете создание объекта Note, включает в себя создание копии с помощью конструктора копирования!

Можете ли вы избежать наличия объекта и вместо этого иметь указатель на объект? Вы можете сделать это, поставив создание внутри функции (фабрика). Эта функция принимает аргументы конструктора, новый объект и возвращает умный указатель.

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