将类型保存到文件

Save a Type to a file

我正在尝试制作一个关卡加载系统,其中关卡文件存储为一些二进制文件,其中包含要生成的对象的 class 及其位置和比例。我无法弄清楚的一件事是如何将 class 类型转换为可以写入二进制文件并稍后检索的类型。

我尝试将其转换为字符串,但如何将 typeid(type).name() 转回 class 类型以生成?

接受任何执行此操作的方法

I tried converting it to a string, but then how do I turn that typeid(type).name() back into the class type to spawn?

你必须以某种方式自己制作它(因为语言中没有任何东西可以 "go the other way" 可以这么说,那就是从 typeid 构造一个对象),例如。使用 switch 语句(或 if/else 结构),ala:

switch (my_type_id) {
//... add cases here for the types you need
}

使用 typeid 的问题是它不是持久的。因此,建议您构建自己的 list/enum 所需类型。

如果你不是在制作自己的 ID/enum 类型并且想使用 typeid,我建议你使用 boost typeindex 而不是 https://www.boost.org/doc/libs/1_59_0/doc/html/boost_typeindex.html,那可能会省去一些意外调试。最简单的可能仍然是为您需要的类型制作自己的枚举。

对于更高级的解决方案,您甚至可以查看 boost serialize library

这里发生了一些事情,所以我冒昧地写了一个简短的片段。

当您不知道它们的类型时,为了将一堆 objects 读入像下面这样的单个容器中,它们都需要从基数 class 派生。或者,您可以传递 deserialize 函数不同的向量(或其他容器)来存储不同的类型。什么都行。

deserialize 函数然后使用 switch 就像@darune 建议的那样构造适当的类型。

有各种各样的序列化/反序列化库,它们可以让您比这更复杂,并存储更复杂的 objects 组。我经常使用 rapidjson for this sort of thing. boost.serialize 是另一种选择(同样是@darune 建议的)。

#include <fstream>
#include <iostream>
#include <vector>

using std::ifstream;
using std::vector;
using std::cout;
using std::endl;

class Object
{
public:
    double position;
    double scale;

    Object(const double& position, const double& scale)
    : position(position), scale(scale) { }

    virtual ~Object() {}
};

class Foo : public Object
{
public:
    static const int id = 0;
    Foo(const double& position, const double& scale)
    : Object(position, scale) { }

};

class Bar : public Object
{
public:
    static const int id = 1;
    Bar(const double& position, const double& scale)
    : Object(position, scale) { }
};

Object* deserialize(int id, const double& position, const double& scale)
{
    switch (id)
    {
        case Foo::id:
            return new Foo(position, scale);
        case Bar::id:
            return new Bar(position, scale);
        default:
            return nullptr;
    };
}

然后一个从文本文件中读入的示例如下所示

int main(void)
{
    vector<Object*> objects;

    ifstream fin;
    fin.open("objects.txt");
    if (!fin)
        throw std::runtime_error("Unable to open file");


    // Read in the id, position and scale from a file
    int id;
    double position, scale;

    while (!fin.eof())
    {
        fin >> id >> position >> scale;
        Object* object = deserialize(id, position, scale);
        if (object != nullptr)
            objects.push_back(object);
    }

    fin.close();

    // Print out the objects
    for (auto pobj: objects)
        cout << pobj->position << " " << pobj->scale << endl;

    // Don't forget to clean up
    for (auto object: objects)
        delete object;
}

在这种情况下,objects.txt 是一个仅以空格分隔的文本文件 id position scale(没有 header)。例如

1 0.4 10
0 0.1 5
0 0.1 1

从二进制读入是类似的。