C ++:制作指针向量的完整副本

时间:2011-11-09 04:11:59

标签: c++ pointers vector

我正在开发C ++游戏。我的关卡对象在一个向量中(Object是我关卡对象的超类)。

我需要将此矢量的状态保存在检查点,并在死亡时检索。

所以在关卡的开头,创建了矢量(对象)(old_objects)。

如果您点击检查点,则会删除old_objects并将对象重新复制到old_objects。

如果你死了,对象中的数据将被删除,old_objects将被复制回对象。

我一直试图通过多种方式做到这一点,但我无法让它发挥作用。帮助

编辑:我尝试使用虚拟clone()方法。它会抛出范围错误。

class Object {
  public:
    virtual Object* clone() { return new Object(); }
};

class SubObjectA {
  public:
    Object* clone() { return new SubObjectA(datablahblah); }
};

class SubObjectB {
  public:
    Object* clone() { return new SubObjectB(datablahblah); }
};

for (vector<Object*>::iterator it = objects.begin(); it != objects.end(); it++) {
    Object* tempobj = *it;
    old_objects.push_back(tempobj->clone());
}

但我得到的只是旧的:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

2 个答案:

答案 0 :(得分:1)

您可以使用Prototype模式并让您的Object基类声明一个纯虚拟clone()方法。然后在检查点时,您只需要迭代指针上的向量调用克隆并将它们推入新向量。

答案 1 :(得分:0)

这里唯一重要的要求是提供一个深度复制构造函数,用于存储所有必要的信息(或者如果不可能,则提供获取所有必需信息的方法)。然后使用该ctor /方法创建第二个向量。类似的东西:

class Object
{
    RenderObject * m_Renderable;
    int m_Health;
    float3 m_Position;

    Object(const Object * other) :
       m_Renderable(nullptr),
       m_Health(other->m_Health), 
       m_Position(other->m_Position)
    { };

    Object * GetStorable()
    {
        return new Object(*this);
    }
};

然后存储“检查点”,你只需:

vector<vector<shared_ptr<Object>>> gCheckpoints;
vector<shared_ptr<Object>> gLevelObjects;

vector<shared_ptr<Object>> checkpoint;
std::for_each(
    gLevelObjects.begin(), gLevelObjects.end(),
    [&](shared_ptr<Object> obj)
    {
        checkpoint.push_back(obj->GetStorable());
    });
gCheckpoints.push_back(checkpoint); // creates a new checkpoint

恢复检查点时,您需要重新创建对象的渲染信息;但是,这是大多数图形环境中大多数保存系统的要求。

根据Object类的设置方式,您还可以从另一个仅包含 存储数据的类继承,只需存储该类并在其中创建可渲染项。必要的(class RenderObject : StoredObject { ... };)。

您也可以以某种方式序列化对象(二进制保存,xml,json)并将其存储到文件(autosave / quicksave / checkpoint)或内存中,然后使用常规加载机制加载该特定文件

最好的方法取决于您的计划以及系统的设置方式,但这个概念应该提供基础知识或给您一个起点。