事实上,这是一个非常基本的问题(你可以想象,你绝对不是唯一一个在C++中反序列化)。
你要找的是虚拟建筑。
C++没有定义虚拟结构,但很容易使用
Prototype
设计图案或使用
Factory
方法。
我个人更喜欢
工厂
接近,因为
原型
一种是有某种类型的默认实例被复制然后定义…问题是并非所有类都有一个有意义的默认值,因此,有意义的
Default Constructor
.
这个
工厂
方法很简单。
-
您需要一个用于消息的公共基类,另一个用于解析器
-
每条消息都有一个标记和一个相关的解析器。
让我们看看一些代码:
// Framework
class Message
{
public:
virtual ~Message();
};
class Parser
{
public:
virtual ~Parser();
virtual std::auto_ptr<Message> parse(std::istream& serialized) const;
};
// Factory of Messages
class MessageFactory
{
public:
void register(std::string const& tag, Parser const& parser);
std::auto_ptr<Message> build(std::string const& tag, std::istream& serialized) const;
private:
std::map<std::string,Parser const*> m_parsers;
};
有了这个框架(公认的简单),一些派生类:
class MessageA: public Message
{
public:
MessageA(int a, int b);
};
class ParserA: public Parser
{
public:
typedef std::auto_ptr<MessageA> result_type;
virtual result_type parse(std::istream& serialized) const
{
int a = 0, b = 0;
char space = 0;
std::istream >> a >> space >> b;
// Need some error control there
return result_type(new MessageA(a,b));
}
};
最后,其用途是:
int main(int argc, char* argv[])
{
// Register the parsers
MessageFactory factory;
factory.register("A", ParserA());
// take a file
// which contains 'A 1 2\n'
std::ifstream file = std::ifstream("file.txt");
std::string tag;
file >> tag;
std::auto_ptr<Message> message = factory.parse(tag, file);
// message now points to an instance of MessageA built by MessageA(1,2)
}
它起作用,我知道因为我使用它(或者是一个变体)。
有一些事情需要考虑:
-
你可能愿意
MessageFactory
它是一个单例,然后允许在库加载时调用它,这样就可以通过实例化静态变量来注册解析器。如果你不想的话,这个很方便
main
要注册每一个解析器类型,就必须:无依赖性的局部性。
-
标签必须共享。标记由消息类(称为标记)的虚拟方法提供服务也不常见。
像:
class Message
{
public:
virtual ~Message();
virtual const std::string& tag() const = 0;
virtual void serialize(std::ostream& out) const;
};
-
序列化的逻辑也必须是共享的,对象处理自己的序列化/反序列化是正常的。
像:
class MessageA: public Message
{
public:
static const std::string& Tag();
virtual const std::string& tag() const;
virtual void serialize(std::ostream& out) const;
MessageA(std::istream& in);
};
template <class M>
class ParserTemplate: public Parser // not really a parser now...
{
public:
virtual std::auto_ptr<M> parse(std::istream& in) const
{
return std::auto_ptr<M>(new M(in));
}
};
模板最棒的是它从不停下来让我惊讶
class MessageFactory
{
public:
template <class M>
void register()
{
m_parsers[M::Tag()] = new ParserTemplate<M>();
}
};
//skipping to registration
factory.register<MessageA>();
现在是不是很漂亮:)?