2016-05-07 11 views
1

Я хочу создать list<unique_ptr<Base>> listOfBaseUniquePtr. Это даст мне обоим:
1. Уникальные ptrs, и
2. Полиморфизм. Я бы мог вызвать виртуальную функцию каждого производного класса.Список unique_ptr, для производного класса шаблонов

Что-то не работает для меня. Посмотрите в следующем примере кода:

#include <iostream> 
#include <list> 
#include <memory> 

using namespace std; 

class Base { 
}; 

list<unique_ptr<Base>> listOfBaseUniquePtr; 

template <typename T> 
class Derived: public Base { 

}; 

int main() { 

    listOfBaseUniquePtr.push_back(new Derived<int>()); // <--- error 
} 

Ошибка:

main.cpp:19:53: error: no matching function for call to
‘std::list >::push_back(Derived)’
listOfBaseUniquePtr.push_back(new Derived()); // <--- error
^main.cpp:19:53: note: candidates are: In file included from /usr/include/c++/4.8/list:63:0,
from main.cpp:2: /usr/include/c++/4.8/bits/stl_list.h:1015:7: note: void std::list<_Tp,
_Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr; _Alloc = std::allocator
std::list<_Tp, _Alloc>::value_type = std::unique_ptr]
push_back(const value_type& __x)
^/usr/include/c++/4.8/bits/stl_list.h:1015:7: note: no known conversion for argument 1 from ‘Derived
’ to ‘const value_type&
{aka const std::unique_ptr&}’
/usr/include/c++/4.8/bits/stl_list.h:1020:7: note: void std::list<_Tp,
_Alloc>::push_back(std::list<_Tp, _Alloc>::value_type&&) [with _Tp = std::unique_ptr; _Alloc = std::allocator
std::list<_Tp, _Alloc>::value_type = std::unique_ptr]
push_back(value_type&& __x)
^/usr/include/c++/4.8/bits/stl_list.h:1020:7: note: no known conversion for argument 1 from ‘Derived*’ to
‘std::list >::value_type&& {aka
std::unique_ptr&&}’ make[2]:
[CMakeFiles/uniqueptr.dir/main.cpp.o] Error 1 make[1]:
[CMakeFiles/uniqueptr.dir/all] Error 2 make: [all] Error 2

Что я делаю неправильно?

+0

'push_back (make_unique >())' должен выполнять эту работу. – Jarod42

ответ

3

Если вы посмотрите на подпись push_back(), вы увидите, что есть две перегрузки. Один берет std::unique_ptr<T> const&, а другой std::unique_ptr<T>&&.

Выражение new Derived<int>() возвращает Derived<int>* тип; очевидно, что это не относится к ранее упомянутым типам; ни одна из перегрузок не имеет параметра Derived<int>*.

Вы можете сделать две вещи:

Заменить

listOfBaseUniquePtr.push_back(new Derived<int>()); 

С

listOfBaseUniquePtr.push_back(std::make_unique<Derived<int>>()); 

Или используйте emplace() семейство функций членов std::list<T>; вот пример:

listOfBaseUniquePtr.emplace_back(new Derived<int>); 

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

class Base 
{ 
public: 
    virtual ~Base() = default; 
}; 
+0

Спасибо, я не смог найти этот 'std :: make_unique', потому что я на g ++ 4.8, а не 4.9 :(. Так что я использовал эту реализацию: http://stackoverflow.com/questions/24609271/errormake-unique-is-not-a-member-of-std – hudac

+1

@hudac Хотя я бы рекомендовал использовать 'std :: make_unique', вы также могли бы просто выполнить' listOfBaseUniquePtr.push_back (std :: unique_ptr > (новый Derived )); '. – user2296177

1

Вы должны использовать std::make_unique:

listOfBaseUniquePtr.push_back(std::make_unique<Derived<int>>()); 

также не забудьте добавить виртуальный деструктор к базе:

virtual ~Base(){} 

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

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