存储指针传染媒介在文件和再读它们

时间:2013-11-01 15:10:18

标签: c++ vector std fstream

假设以下代码:

// Base class
class Base {
public:
    Base(int val) : hi(val) {
    }
    virtual void PublicMethod() { /* Do something */}

private:
    int hi;
};

// Child class
class Child : public Base {
public:
    Child(int val) : Base(val) {
    }
    void PublicMethod() { /* Do something */}
};

// Vector of pointers to prevent slicing
std::vector<std::shared_ptr<Base>> list;

(...) // Fill list with mixed data of class Base and Child

列表填充对象后,我想将数据存储到文件中。为此,我尝试了以下方法:

std::ofstream os("data.txt", std::ios::out);

int size1 = list.size();
os.write((const char*)&size1, sizeof(int));
for (auto it = list.begin(); it < list.end(); ++it) {
    os.write((const char*)(*it), size1 * sizeof(Base));
}
os.close();

但是我不确定这是否正确,从文件中读取数据似乎也无法正常工作。我担心当我保存数据时sizeof(Base)也不适用于其子对象,这些对象的大小可能不同。

即使这项工作正常,是否有更好的方法将实际数据存储到文件中,如何轻松读取文件中的数据并将其存储在shared_ptr<Base>矢量列表中?

任何例子都会有很大的帮助。

1 个答案:

答案 0 :(得分:2)

您需要为对象提供某种形式的序列化。这是一个非常简单的例子(不包括错误检查,类型构造等)。

此示例显示了最原始的序列化类型,但它足以提供您需要执行的操作的示例。

当你开始处理派生类时,它会变得更加棘手,因为你需要一些工厂方法来根据你序列化的一些sentinel值来正确地创建类型。

#include <string>
#include <iostream>
#include <sstream>
using namespace std;

class A
{
public:
    A()
        : a_(0)
    {
    }

    A(int a, const string& n)
        : a_(a), n_(n)
    {
    }

    // a function to write objects to a stream    
    friend ostream& operator<<(ostream& stream, const A& obj);

    // a function to read objects from a stream
    friend istream& operator>>(istream& stream, A& obj);

private:
    int a_;
    string n_;
};

ostream& operator<<(ostream& out, const A& obj)
{
    out << obj.a_ << ' ' << obj.n_;
    return out;
}

istream& operator>>(istream& in, A& obj)
{
    in >> obj.a_ >> obj.n_;
    return in;
}


int main()
{
    A one(1, "one");
    A also_one;

    string buffer;
    stringstream serializer;

    // write out your source object to a stream and "store it"
    // here we simply store it in a string    
    serializer << one;
    buffer = serializer.str();

    // using the "stored" value, read the stored values
    // into an (already constructed) object
    stringstream deserializer(buffer);
    serializer >> also_one;

    // verify the output is the same
    cout << one << " is the same as " << also_one << "\n";
}