Глубокая копия std :: vector указателей на базовый класс - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть std::vector<std::unique_ptr<BaseType>>.Есть ли какой-нибудь чистый способ сделать глубокую копию vector?

Единственное, о чем я могу подумать, это иметь функцию, которая использует dynamic_cast для извлечения производного типа, а затем скопировать этов новый объект, удерживаемый unique_ptr.Учитывая, что у меня есть контроль над всеми возможными производными классами, это было бы возможно.У этого есть все виды очевидных недостатков.

Ранее я использовал единственный класс, который был объединением всех производных типов.Пытаясь уйти от этого, я столкнулся с необходимостью скопировать vector.

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


vector является членом класса, который должен быть копируемым.Итак, в этом случае мне просто нужно убедиться, что я могу написать конструктор копирования для содержащего класса.

1 Ответ

0 голосов
/ 19 сентября 2018

Самый простой способ - реализовать некоторую форму клонирования, используя std::transform:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <vector>

struct base {
    // For constructors and destructors, it's business as usual.
    // Remember to implement the rule of five.
    base() {std::cout << "new base\n";}
    base(const base& o) {
        std::cout << "copied base\n";
    }
    virtual ~base() {std::cout << "destructed base\n";}
    // This is the virtual copy function. We need this because only
    // the actual derived class will know how to copy itself. The
    // only way to forward this knowledge to a pointer to the base 
    // class is via a virtual function.
    // You can make this pure virtual, if you don't mind
    // the base being abstract (or if you *want* to make it 
    // abstract). It'll be safer this way.
    virtual base* copy() {return new base(*this);}
};

struct derived : base {
    derived() : base() {std::cout << "new derived";}
    derived(const derived& o) : base(o) {
        std::cout << "copied derived\n";
    }
    virtual ~derived() {std::cout << "destructed derived\n";}
    base* copy() override {return new derived(*this);}
};

// example of deep copying
int main() {
    std::vector<std::unique_ptr<base>> v;
    v.emplace_back(new base());
    v.emplace_back(new derived());
    std::vector<std::unique_ptr<base>> copy_of_v;

     // The transformation merely calls copy(). Each object will be copied into
     // an instance of the correct type. 
    std::transform(v.begin(), v.end(), std::back_inserter(copy_of_v), [](auto& item){
        return std::unique_ptr<base>(item->copy());
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...