我有一个班级NodeManager
。它基本上保留了Node*
s列表以及它们之间的连接。实际上它管理的节点是从Node
类派生的类。
现在我希望这个NodeManager
能够保存它的所有节点并将其加载回来。
我面临的问题是如何存储节点的派生类型。
我在考虑存储派生类的typeid
并保留Node
可以派生的可能类型的列表,但我不知道如何才能实现。< / p>
性能不是问题,无论如何我们都在谈论&lt; 100个节点。
答案应该在windows,linux和mac os上运行多平台。
我希望答案是在不改变NodeManager
的代码的情况下,尽可能减少添加更多节点类型。
答案 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_ptr
或boost::shared_ptr
代替QSharedPointer
。