1

我已尝试仔细阅读C++FAQ中有关此主题的所有建议。我已经根据项目 36.8实现了我的系统,现在几个月后(有很多数据序列化),我想对一些类的公共接口和继承结构本身进行更改。

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. 拆分DerivedDerived1Derived2,同时将原始数据映射DerivedDerived1现有数据。

  2. 拆分Base::field1()Base::field1a()Base::field1b()同时映射field1到现有数据field1a并为field1b空。

我将必须

  1. 反序列化所有千兆字节的旧数据
  2. 将它们转换为新的继承结构
  3. 以一种新的、更灵活的方式重新序列化它们。

我想知道如何让序列化更灵活,这样当我决定将来做一些改变时,我就不会像现在一样面临转换地狱。

我想制作一个使用数字而不是名称来序列化我的对象的系统。例如 Base = 1, Derived1 = 2, ... 和一个单独的number-to-name系统,可以将 numbers 转换为 names,所以当我想更改某个类的名称时,我只会在这个单独的数字到名称系统,无需更改数据。

这种方法的问题是:

  1. 系统会很脆弱。那就是改变数字到名称系统中的任何东西都可能改变千兆字节数据的含义。

  2. 序列化数据会失去一些人类可读性,因为在序列化数据中,会有数字而不是名称。

很抱歉将这么多问题放在一个问题上,但我对编程缺乏经验,而且我面临的问题似乎如此巨大,以至于我不知道从哪里开始。

任何关于灵活连载的通用材料、教程、习语或文献都非常受欢迎!

4

2 回答 2

2

现在可能有点晚了,但是在设计序列化格式时,您应该提供版本控制。这可以被修改为流中的类型信息,或者被视为一个单独的(整数)字段。在编写课程时,您始终编写最新版本。阅读时,必须先阅读类型和版本,然后才能构造;如果您使用的是常见问题解答中建议的静态地图,那么关键是:

struct DeserializeKey
{
    std::string type;
    int version;
};

鉴于您现在所处的情况,解决方案可能是以清晰可辨的方式将版本更改为类型名称,例如 :如果 后面没有两个下划线,则使用0。这不是最有效的方法,但通常可以接受,并且可以通过向后兼容性解决问题,同时为将来的演进做好准备。type_name__versiontype_name

对于您的确切问题:

  1. 在这种情况下,Derived它只是 Derived1. 您可以在适当的键下将必要的工厂函数插入到映射中。

  2. 这只是经典的版本控制。版本 0Base有一个field1属性,当你反序列化时,你用它来初始化field1a,你初始化为field1b空。版本 2Base两者都有。

如果您将版本更改为类型名称,正如我上面建议的那样,您不必转换任何现有数据。当然,从长远来看,要么一些旧版本从你的数据集中消失,这样你就可以取消对它们的支持,或者你的程序变得越来越大,支持很多旧版本。在实践中,我通常看到后者。

于 2013-05-21T16:51:33.963 回答
0

也许Thrift可以帮助你做到这一点。

于 2013-05-21T16:39:33.170 回答