在文件中存储类的类型

时间:2013-10-12 15:02:11

标签: c++

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

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

我在考虑存储派生类的typeid并保留Node可以派生的可能类型的列表,但我不知道如何才能实现。< / p>

性能不是问题,无论如何我们都在谈论&lt; 100个节点。 答案应该在windows,linux和mac os上运行多平台。 我希望答案是在不改变NodeManager的代码的情况下,尽可能减少添加更多节点类型。

1 个答案:

答案 0 :(得分:2)

在基类中,创建返回某种“ID”的抽象虚方法。 (string,int,enum,whatever)。

在“save”方法中,首先为所有类写入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