2017-02-15 24 views
1

Редактирование старого кода, в котором я вручную обрабатывал время жизни вектора необработанных указателей для конкретных экземпляров абстрактного базового класса (ABC).How/Возможно ли иметь вектор <unique_ptr <ABC>>?

Так владелец вектора был виртуальный dtor который вручную прошел и удалил содержимое вектора и т.д.

Поскольку владелец вектора имеет элементы в ней, он делает много смысла, чтобы изменить это вектор unique_ptr.

К сожалению, кажется, это невозможно? Поскольку vector<unique_ptr<type>> должен быть в состоянии иметь статический dtor для type, но потому, что в данном случае тип является ABC, который не доступен, поэтому vector не будет компилировать ...

Или я что-то отсутствует?

например:

struct ABC 
{ 
    ABC() = default; 
    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
}; 

EDIT2: вот полный пример, который терпит неудачу:

#include <iostream> 
#include <memory> 
#include <vector> 

struct ABC 
{ 
    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
}; 

struct Child : ABC 
{ 
    std::unique_ptr<ABC> Clone() override { return std::make_unique<Child>(*this); } 
    void Foo() override { }; 
}; 

struct Derived : Child 
{ 
    std::unique_ptr<ABC> Clone() override { return std::make_unique<Derived>(*this); } 
}; 

int main() 
{ 
    std::unique_ptr<ABC> x; 
    std::unique_ptr<ABC> c = std::make_unique<Child>(); 

    std::vector<std::unique_ptr<ABC>> elements; 
    elements.emplace_back(std::make_unique<Derived>()); 
    return 0; 
} 
+0

Не уверен, что все остальные, но если вы используете одни и те же имена из примера кода в вопросе он делает то, что вы просите много понятнее , Тем не менее, какая ошибка вы получаете? Ваш код кода компилируется для меня. – NathanOliver

+0

Не могли бы вы просто отправить объявление Base? Прямо перед тем, как вы это определите? –

+0

Я получаю длинный набор сообщений от VS 2015 Upd 3, который в основном не создает экземпляр «элементов» по ​​умолчанию для вектора из-за удаления ctor в Base (предположительно потому, что это ABC) – Mordachai

ответ

4

Ошибка возникает при попытке скопировать экземпляр Base или экземпляр типа, полученный из Base , Конструктор копии по умолчанию попытается скопировать Base::elements, который пытается скопировать каждый из его элементов в новый vector. Поскольку эти элементы являются unique_ptr<Base>, эта копия не допускается.

Этот пример воспроизводит проблему:

#include <memory> 
#include <vector> 

struct Base 
{ 
    using PBase = std::unique_ptr<Base>; 
    using VBase = std::vector<PBase>; 

    VBase elements; 
}; 

int main() 
{ 
    Base x; 
    auto y = x; // This line causes the error 

    return 0; 
} 

Вы, вероятно, нужно реализовать свой собственный конструктор копирования и копирования оператора присваивания, или запретить копирование путем удаления этих функций. Вместо этого может работать shared_ptr, если мелкие копии будут работать для вашего приложения.

+0

Спасибо. Я просто не видел очевидного. Весьма признателен. – Mordachai

0

Для полноты, вот что я должен был делать:

class ABC 
{ 
public: 
    ABC() = default; 
    ABC(const ABC & rhs) 
    { 
     // manually clone our elements 
     elements.reserve(rhs.elements.size()); 
     for (const auto & e : rhs.elements) 
      elements.emplace_back(e->Clone()); 
    } 
    ABC & operator = (const ABC &) = delete; 

    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
};