我有一个抽象类对象,它看起来是这样的:
class Object
{
public:
Object();
virtual void DoSomething() = 0;
virtual void Save(std::ofstream &file) = 0;
virtual void Load(std::ifstream &file) = 0;
};
我还有类球和文本框:
class Ball : public Object
{
public:
Ball(int x, int y, int z)
{
m_x = x; m_y = y; m_z = z;
}
void DoSomething()
{
std::cout << m_x << ", " << m_y << ", " << m_z << std::endl;
}
void Save(std::ofstream &file)
{
file << m_x << " " << m_y << " " << m_z << std::endl;
}
void Load(std::ifstream &file)
{
file >> m_x >> m_y >> m_z;
}
private:
int m_x, m_y, m_z;
};
class TextBox: public Object
{
public:
TextBox(std::string message)
{
m_message = message;
}
void DoSomething()
{
std::cout << m_message << std::endl;
}
void Save(std::ofstream &file)
{
file << m_message << std::endl;
}
void Load(std::ifstream &file)
{
file >> m_message;
}
private:
std::string m_message;
};
我有一个指向这些对象的指针向量:
std::vector<Object*> objects;
objects.push_back(new Ball(1, 2, 3));
objects.push_back(new TextBox("Hello world!"));
for (Object *o : objects) o->DoSomething();
我想把这个矢量保存到文件中。 这很容易。 我做了这样的东西:
std::ofstream file("foo.txt");
for (Object *o : objects) o->Save(file);
file.close();
现在我要加载这个。 这里有个问题。 我如何指定,哪个对象(球或文本框)我应该加载? 我可以使用一些索引,比如:
void Ball::Save(std::ofstream &file)
{
file << 1 << " " << m_x << " " << m_y << " " << m_z << std::endl;
}
void TextBox::Save(std::ofstream &file)
{
file << 2 << " " << m_message << std::endl;
}
然后,在阅读了这个索引之后,我知道,这是一个球或者一个文本框。
int index;
Object *o;
file >> index;
switch (index)
{
case 1: o = new Ball(0, 0, 0); break;
case 2: o = new TextBox(""); break;
}
o->Load(file);
objects.push_back(o);
但是有没有更好的方法来存储这种结构呢? 如果我有100个对象的继承者呢? 我能以某种方式避免100开关情况吗?
您提出的这些“索引”通常被称为“元数据”。 还有其他语言,比如Java,支持反射功能,但是C++中的反射功能仍在考虑之中。 出于这个原因,我建议实现某种抽象接口,它将返回对象的确切类的信息。
此外,我建议查看序列化库,这可以简化保存和读取数据的过程。 您可以尝试从boost开始:https://www.boost.org/doc/libs/1_73_0/libs/serialization/doc/index.html
我必须承认,很久以前我就使用过boost序列化,但我记得它相当好用。