我已尝试仔细阅读 C++FAQ 中给出的所有建议。关于这个问题。我已经根据项目 36.8 实现了我的系统,现在几个月后(大量数据序列化),我想对某些类的公共(public)接口(interface)和继承结构本身进行更改。
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";}
};
我想知道如何进行更改,例如:
将
Derived
拆分为Derived1
和Derived2
,同时将原来的Derived
映射到Derived1
用于现有数据。映射时将
Base::field1()
拆分为Base::field1a()
和Base::field1b()
field1
到field1a
并为现有数据设置field1b
为空。
我必须要
- 反序列化所有千兆字节的旧数据
- 将它们转换为新的继承结构
- 以更灵活的新方式重新序列化它们。
我想知道如何让序列化更灵活,这样当我决定在未来做一些改变时,我就不会像现在这样面临转换 hell 。
我想制作一个使用数字而不是名称 来序列化我的对象的系统。例如 Base = 1, Derived1 = 2, ... 和一个单独的number-to-name 系统,它将将数字转换为名称,这样当我想要更改某些类的名称,我只会在这个单独的数字到名称系统中进行,而不更改数据。
这种方法的问题是:
系统会脆弱。也就是说,改变从数字到名字的系统中的任何内容都可能改变千兆字节数据的含义。
序列化数据会失去一些人类可读性,因为在序列化数据中,会有数字而不是名称。
很抱歉把这么多问题放在一个问题中,但我在编程方面缺乏经验,而且我面临的问题似乎难以应付,我只是不知道从哪里开始。
欢迎任何关于灵活序列化的一般 Material 、教程、习语或文献!
最佳答案
现在可能有点晚了,但是每当设计 一种序列化格式,您应该提供版本控制。 这可以被混淆到流中的类型信息中,或者 被视为一个单独的(整数)字段。写类的时候 out,你总是写最新的版本。阅读时,你 必须先阅读类型和版本 构造;如果您使用常见问题解答中建议的静态 map , 那么关键是:
struct DeserializeKey
{
std::string type;
int version;
};
鉴于您现在的情况,解决方案可能是
以清晰可辨的方式将版本转换为类型名称
方式,说些类似的话
<i>type_name</i>__<i>version</i>
;如果
<i>type_name</i>
后面没有两个下划线,
然后使用 0。这不是最有效的方法,但它是
通常可以接受,并且会用 backwards 解决问题
兼容性,同时为 future 的发展提供支持。
对于您的确切问题:
在这种情况下,
Derived
只是以前的版本Derived1
.您可以将必要的工厂功能插入到 相应键下的 map 。这只是经典的版本控制。
Base
的版本 0有 一个field1
属性,当你反序列化时,你用它来 初始化field1a
, 然后你初始化field1b
空的。Base
的第 2 版两者都有。
如果你按照我的建议将版本改成类型名称 上面,您不必转换任何现有数据。长的 术语,当然,一些旧版本只是 从你的数据集中消失,这样你就可以删除 支持他们,或者你的程序越来越大, 支持许多旧版本。在实践中,我通常 看到了后者。
关于c++ - 如何对多态继承层次结构进行灵活的序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16674806/