C++ 如何执行多态继承层次结构的灵活序列化?
我试图仔细阅读报告中关于这个问题的所有建议。我已经根据第36.8项实现了我的系统,几个月后(大量数据序列化),我想对一些类的公共接口和继承结构本身进行更改C++ 如何执行多态继承层次结构的灵活序列化?,c++,serialization,C++,Serialization,我试图仔细阅读报告中关于这个问题的所有建议。我已经根据第36.8项实现了我的系统,几个月后(大量数据序列化),我想对一些类的公共接口和继承结构本身进行更改 class Base { public: Vector field1() const; Vector field2() const; Vector field3() const; std::string name() const {return "Base";} }; class Derived : public
class Base
{
public:
Vector field1() const;
Vector field2() const;
Vector field3() const;
std::string name() const {return "Base";}
};
class Derived : public Base
{
public:
std::string name() const {return "Derived";}
};
我想知道如何进行更改,例如:
派生的
拆分为派生的1
和派生的2
,同时将原始的派生的
映射到现有数据的派生的1
Base::field1()
拆分为Base::field1a()
和Base::field1b()
,同时将field1
映射到field1a
,并使现有数据的field1b
为空任何关于灵活序列化的通用材料、教程、习语或文献都是最受欢迎的 也许可以帮你做这件事。现在可能有点晚了,但无论何时 如果是序列化格式,则应提供版本设置。 这可能会损坏流中的类型信息,或者 作为单独的(整数)字段处理。写课文的时候 你总是写最新的版本。读书的时候,你 必须先阅读类型和版本,然后才能 建构;如果您使用的是常见问题解答中建议的静态映射, 那么关键是:
struct DeserializeKey
{
std::string type;
int version;
};
考虑到你现在的处境,解决办法可能是
以清晰可识别的方式将版本更改为类型名称
顺便说一句,说点关于
type_name___版本
;如果
type_name
后面没有两个下划线,
然后使用0。这不是最有效的方法,但它是
通常是可以接受的,并且可以解决向后的问题
兼容性,同时提供未来的进化
关于你的确切问题:
派生的
只是
Derived1
。您可以将必要的factory函数插入到
将地图放在相应的键下Base的版本0已发布
一个field1
属性,当反序列化时,使用它
初始化field1a
,然后将field1b
初始化为空。
Base
的第2版同时具有这两种功能
可以看到后者。您不需要数字到名称或名称到数字的转换。您需要程序实体(类型、字段)到(外部的、可序列化的)名称映射。源代码中为这些实体指定的名称并不完全相关。您可以使用源名称作为默认外部名称,但应该有可能覆盖该名称。映射也不必是1:1,您可能希望将
class NewWidget
写入“NewWidget”,但将“Widget”和“NewWidget”读取为class NewWidget
。此外,如果某个字段具有合理的默认值,则只需在序列化数据中找不到其值时使用它。这样你就可以不费吹灰之力地引入新的领域。这将自动满足您90%的需求。对于其他10%的需求,您将需要编写转换代码。永远不要从代码中删除旧的类和字段。为它们编写后反序列化例程,将它们转换为较新的对象。我非常喜欢将格式版本号添加到数据文件中(从第一个版本开始),以便读取它们的软件知道它在处理什么,并可能根据需要进行转换。@Loadmaster如果我理解正确,您保持旧数据“原样”,保留旧反序列化代码并将其应用于旧数据?谢谢,但您的链接对我来说太高级了。我不知道他们在说什么:(@MartinDrozdik,这对你来说似乎有点太晚了。(还有谷歌协议块。)通常情况下,序列化代码是生成的,而不是手工编写的,生成器会处理我在回答中提到的所有问题。但是,对于我来说,您找到一个生成器的可能性似乎很小,它会以某种奇迹般的危险生成您所使用的格式。谢谢!这是exac