0

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

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

我正在考虑存储typeid派生类的内容并保留Node可以派生的可能类型列表,但我不知道如何才能做到这一点。

性能不是问题,无论如何我们谈论的是<100 个节点。答案应该适用于 windows、linux 和 mac os 上的多平台。如果可能的话,我希望答案是让添加更多节点类型变得微不足道,而无需更改NodeManager.

4

1 回答 1

2

在基类中,创建返回某种“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

于 2013-10-12T15:34:44.607 回答