在C ++中存储类集合(非托管) [英] Store class collection in c++ (unmanaged)

查看:62
本文介绍了在C ++中存储类集合(非托管)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好
我正在学习c ++,前几天我在将对象集合保存到文件并读回它们时遇到了一些困难.您能给我一个有关这个问题的提示吗?
问题是:我有一个基类和一个派生类.我还具有派生类的对象的ArrayList,并且必须将此ArrayList写入磁盘上的文件,然后再读取它.

谢谢.

Hello
i am learning c++, and the other day i had some difficulties with saving collections of object to file and reading them back. Could you please give me a hint with this question?
Question is followind:i have one base class, and one derived class. I have also ArrayList of objects of derived class, and i have to write this ArrayList to file on disk, and then read it.

Thank you.

推荐答案

我建​​议您研究一下boost序列化.请从这里开始:
http://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29 [^ ],
http://www.boost.org/ [ ^ ],
http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html [ ^ ].

—SA
I would advise you to look into boost serialization. Please start here:
http://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29[^],
http://www.boost.org/[^],
http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html[^].

—SA


不幸的是,您将不得不用C ++为自己编写整个序列化代码.如果您要做的就是只保存一个对象数组,然后加载它,那么您将获得一个非常简单的解决方案.如果需要更通用的序列化支持,则必须使用针对您的问题的库或编写自己的框架,但是即使使用这种解决方案也有些混乱.

让我们假设您要保存的只是一个指向基类的对象指针数组.
保存:
首先,您要对数组的大小进行序列化,然后对对象进行一个接一个的序列化.您可以通过在基类中引入虚拟Serialize(Serializer& ser)方法来进行对象序列化,并在遍历数组时在每个对象上调用此序列化方法.每个对象必须保存一个唯一的标识符,该标识符标识给定的类型/类,然后标识恢复内部状态所需的数据.标识符必须是可序列化类型/类中的唯一ID,例如,为了简单起见,可以使用该类的名称.

正在加载:
首先,您加载数组的大小并设置实际数组实例的大小.然后,您遍历数组,并为数组中的每个项目调用一个魔术函数,该魔术函数通过从流中读取对象来创建对象.保存时,此魔术函数必须以某种方式知道您的Serialize()函数调用中可能出现的每个标识符. magic函数读取类型标识符,检查必须实例化的类,将其实例化,然后调用其虚拟Deserialize(Deserializer& dser)方法,该方法从流中读取其余数据.此魔术函数使用if-else构造检查标识符,或从注册表中获取创建者函数,在注册表中您可以动态注册新类型.

Iam心情很好,所以我为您创建了一个片段,演示了我上面描述的内容:
Unfortunately you will have to write the whole serialization code for yourself in C++. If all you have to do is saving out only an array of objects and then loading it you will get away with quite a simple solution. If you need a much more general serialization support then you will have to use a library that aims your problem or write your own framework but even using such a solution is a bit messy.

Lets assume all you want to save is an array of object pointers to the base class.
Saving:
first you serialize the size of the array, and then the objects one-by-one. You can do the object serialization by introducing a virtual Serialize(Serializer& ser) method to your base class and you call this serialize method on each object while you are iterating over the array. Each object must save a unique identifier that identifies the given type/class and then the data that is needed to restore the inner state. The identifier must be a unique id among the serialzable types/classes, this can be for example the name of the class for the sake of simplicity.

Loading:
First you load the size of the array and set the size of your actual array instance. Then you iterate over the array and for each item in the array you call a magic function that reads creates an object by reading it from the stream. This magic function must somehow know every identifier that can occur in your Serialize() function calls when saving. The magic function reads the type identifier, checks which class must be instantiated, instatiates the class and calls its virtual Deserialize(Deserializer& dser) method that reads the rest of the data from the stream. This magic function check the identifier with an if-else construct or gets the creator function from a registry in which you can register new types dynamically.

Iam in good mood so I created you a snippet that demonstrates what I described above:
class CSerializer
{
public:
    // Write method for every primitive type you support
    void Write(const char&);
    void Write(const int&);
    void Write(const size_t&);
    void Write(const bool&);
    void Write(const float&);
    void Write(const char*);
    void Write(const std::string&);
};

class CDeserializer
{
public:
    // Read method for every primitive type you support
    void Read(char&);
    void Read(int&);
    void Read(size_t&);
    void Read(bool&);
    void Read(float&);
    void Read(std::string&);
};

class CBaseClass
{
public:
    virtual ~CBaseClass() {}
    virtual void Serialize(CSerializer& ser) = 0;
    virtual void Deserialize(CDeserializer& dser) = 0;
};

class CDerivedClass : public CBaseClass
{
public:
    virtual void Serialize(CSerializer& ser)
    {
        ser.Write("CDerivedClass");
        ser.Write(m_DerviedClassState);

    }
    virtual void Deserialize(CDeserializer& dser)
    {
        dser.Read(m_DerviedClassState);
    }
private:
    int m_DerviedClassState;
};

class CDerivedClass2 : public CBaseClass
{
public:
    virtual void Serialize(CSerializer& ser)
    {
        ser.Write("CDerivedClass2");
        ser.Write(m_DerviedClassState);
        ser.Write(m_DerviedClassState2);

    }
    virtual void Deserialize(CDeserializer& dser)
    {
        dser.Read(m_DerviedClassState);
        dser.Read(m_DerviedClassState2);
    }
private:
    std::string m_DerviedClassState;
    bool m_DerviedClassState2;
};


std::vector<CBaseClass*> my_array;


void Serialize(CSerializer& ser)
{
    size_t size = my_array.size();
    ser.Write(size);
    for (size_t i=0; i<size; ++i)
        my_array[i]->Serialize(ser);
}

CBaseClass* DeserializeObject(CDeserializer& dser)
{
    std::string class_id;
    dser.Read(class_id);
    CBaseClass* obj = NULL;
    if (class_id == "CDerivedClass")
        obj = new CDerivedClass;
    else if (class_id == "CDerivedClass2")
        obj = new CDerivedClass2;

    // if obj is NULL its a fatal error but for now I dont do error handling
    obj->Deserialize(dser);
    return obj;
}

void Deserialize(CDeserializer& dser)
{
    size_t size;
    dser.Read(size);
    my_array.resize(size);
    for (size_t i=0; i<size; ++i)
        my_array[i] = DeserializeObject(dser);
}


这篇关于在C ++中存储类集合(非托管)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆