【问题标题】:Storing vector of pointers in a file and reading them again将指针向量存储在文件中并再次读取它们
【发布时间】:2013-11-01 15:10:18
【问题描述】:

假设以下代码:

// 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&lt;Base&gt; 向量列表中?

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

【问题讨论】:

  • 那里有很多错误。取消引用迭代器将获得 shared_ptr,而不是它包装的指针指向的对象。我什至无法建造它!即使使用对象,您也不能将其转换为字节块。您需要查看序列化,并重载运算符 write() 方法,该方法接受一个ofstrem,然后将其成员写入。
  • 您需要为您的类型提供适当的序列化和反序列化 (en.wikipedia.org/wiki/Serialization)。
  • 这样不行。您不能将指针存储在文件中,这是因为地址仅在运行时有效并且如果您不释放它们。您需要做的是序列化数据,然后将它们写入文件。这意味着您必须存储值而不是地址。
  • @user1158692 对不起,我的错。我试图缩短它但没有测试它。感谢有关序列化和&lt;&lt; 运算符的提示。 @chad 我现在正在调查,谢谢。 @thebaconing 这正是我想要做的。

标签: c++ vector std fstream


【解决方案1】:

您需要为您的对象提供某种形式的序列化。这是一个非常简单的示例(省略了错误检查、类型构造等)

这个例子展示了最原始的序列化类型,但它足以提供一个你需要做什么的例子。

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

#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";
}

【讨论】:

  • 我正在处理派生类。 “工厂方法”是什么意思?是否可以在实际转换之前查看序列化字符串应该转换为哪种类型?
猜你喜欢
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 2020-09-17
相关资源
最近更新 更多