Мне нужно скопировать вектор полиморфных объектов, в новом векторе должны быть указатели на те же полиморфные типы, просто не указывающие на одни и те же данные, а вместо этого они должны указывать на новые данные в куче. Эти данные должны быть установлены на те же данные, что и исходный вектор.
пример
std::vector < Component * > entity = baseEntity;
в этом случае новая векторная сущность просто получает указатели от baseEntity. Слайсинг здесь не происходит, но когда я меняю указатель в baseEntity, он также меняет данные в сущности. Как мне правильно скопировать его для моей ситуации?
Вот пример клонирования:
#include <memory>
#include <vector>
struct Component {
virtual std::unique_ptr<Component> clone() const = 0;
};
struct AComponent : Component {
virtual std::unique_ptr<Component> clone() const
{
return std::unique_ptr<Component>(new AComponent(*this));
}
};
struct BComponent : Component {
virtual std::unique_ptr<Component> clone() const
{
return std::unique_ptr<Component>(new BComponent(*this));
}
};
int main(int,char**)
{
std::vector<std::unique_ptr<Component>> old_entities;
old_entities.push_back(std::unique_ptr<Component>(new AComponent));
old_entities.push_back(std::unique_ptr<Component>(new BComponent));
std::vector<std::unique_ptr<Component>> new_entities;
new_entities.reserve(old_entities.size());
for (auto &entity : old_entities) {
new_entities.push_back(entity->clone());
}
}
Чтобы достичь этого, вы должны предоставить метод для клонирования объектов полиморфным способом, то есть предоставляющий переопределяемую функцию клонирования:
class Base
{
public:
virtual std::unique_ptr<Base> clone() = 0;
};
class Foo : public Base
{
int _class_stuff;
public:
virtual std::unique_ptr<Base> clone()
{
return std::unique_ptr(new Foo(*this)); //Calls copy ctor
}
};
Теперь при копировании вектора переместите его, вызывая метод clone каждого элемента:
std::vector<std::unique_ptr<Base>> clone_vector(const std::vector<std::unique_ptr<Base>>& vector)
{
std::vector<std::unique_ptr<Base>> result;
for(auto& element : vector)
result.push_back(element->clone());
return result;
}