c++ - 在文件中存储类的类型

标签 c++

我有一个类 NodeManager。它基本上保留了一个 Node* 列表以及它们之间的连接。实际上,它管理的节点是从 Node 类派生的类。 现在,我希望此 NodeManager 能够保存所有节点并将其归档并加载回来。

我面临的问题是如何存储节点的派生类型。

我正在考虑存储派生类的 typeid 并保留 Node 可以派生到的可能类型的列表,但我不知道如何我能做到吗?

性能不是问题,无论如何我们谈论的是 <100 个节点。 答案应该适用于 windows、linux 和 mac os 的多平台。 我想要的答案是在不更改 NodeManager 代码的情况下,尽可能轻松地添加更多节点类型。

最佳答案

在基类中,创建返回某种“ID”的抽象虚方法。 (字符串、整数、枚举等等)。

在“保存”方法中,首先为所有类写入ID。您可以将 ID 写入基类,因此派生类不会覆盖此行为。

typedef SomeType ClassId;

class Serializeable{
protected:
   virtual ClassId getClassId() const = 0;
   virtual void saveData(OutStream &out) = 0;
public:
   void save(OutStream &out){
       out << getClassId();
       saveData(out);
   }
};

创建一个工厂,根据其 ID 构造所需的类。

--编辑--

工厂示例(C++03 标准):

#include <map>
#include <string>
#include <iostream>
#include <QSharedPointer>
#include <utility>

typedef std::string ClassId;
typedef std::ostream OutStream;

class Serializeable{
protected:
    virtual void saveData(OutStream &out) = 0;
public:
    virtual ClassId getClassId() const = 0;
    void save(OutStream &out){
        out << getClassId();
        saveData(out);
    }
    virtual ~Serializeable(){
    }
};

class Derived: public Serializeable{
protected:
    virtual void saveData(OutStream &out){
        out << "test";
    }
public:
    virtual ClassId getClassId() const{
        return "Derived";
    }
};

typedef QSharedPointer<Serializeable> SerializeablePtr; //basically std::shared_ptr

SerializeablePtr makeDerived(){
    return SerializeablePtr(new Derived());
}

class ClassFactory{
protected:
    typedef SerializeablePtr (*BuilderCallback)();
    typedef std::map<ClassId, BuilderCallback> BuilderMap;
    BuilderMap builderMap;

    template<class C> static SerializeablePtr defaultBuilderFunction(){
        return SerializeablePtr(new C());  
    }

public:
    SerializeablePtr buildClass(ClassId classId){
        BuilderMap::iterator found = builderMap.find(classId);
        if (found == builderMap.end())
            return SerializeablePtr();//or throw exception

        return (*(found->second))();
    }

    void registerClass(ClassId classId, BuilderCallback callback){
        builderMap[classId] = callback;
    }
    template<typename T> void registerClassByValue(const T &val){
        registerClass(val.getClassId(), ClassFactory::defaultBuilderFunction<T>);
    }
    template<typename T> void registerClassWithTemplate(ClassId classId){
        registerClass(classId, ClassFactory::defaultBuilderFunction<T>);
    }
};


int main(int argc, char** argv){
    ClassFactory factory;

    std::string derivedId("Derived");
    factory.registerClass(derivedId, makeDerived);
    SerializeablePtr created = factory.buildClass(derivedId);
    created->save(std::cout);
    std::cout << std::endl;

    Derived tmp;
    factory.registerClassByValue(tmp);
    created = factory.buildClass(derivedId);
    created->save(std::cout);
    std::cout << std::endl;

    factory.registerClassWithTemplate<Derived>(derivedId);
    created = factory.buildClass(derivedId);
    created->save(std::cout);
    std::cout << std::endl;
    return 0;
}

QSharedPointer 是 Qt 4 的智能指针类,大致相当于 std::shared_ptr。在您的代码中使用 std::shared_ptrboost::shared_ptr 而不是 QSharedPointer

关于c++ - 在文件中存储类的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19335604/

相关文章:

c++ - 初始化指针,c 和 c++ 编译器之间的区别 (gcc-4.3.4)

c++ - 围绕 shared_ptr 构建对象系统

c++ - 编写 tcp 服务器——缓冲流

c++ - 类型转换签名到无符号

c++ - 如何连接矩阵?

c++ - 将左值绑定(bind)到引用

c++ - 显式指定位于模板参数包之后的默认模板参数

C++:将变量从main外部的函数传递到main内部的函数调用

c++ - 使用享元模式在位图对象之间共享位图

c++ - 左值需要作为赋值 C++ 数组的左操作数