【问题标题】:Adding new members to C++ structure and backwards compatibility向 C++ 结构和向后兼容性添加新成员
【发布时间】:2017-07-11 09:11:32
【问题描述】:

我有一个其他人在某处使用的结构,他们也依赖sizeof(struct S)。下面是我的结构,

struct S{
   int  aVar1;
   void *ptr1;
}

将来,我可能会向它添加新成员(现在不确定),例如..

struct S{
   int  aVar1;
   void *ptr1;
   int aVar2;
   void *ptr2;
}

我知道这破坏了与依赖 sizeof 的用户的向后兼容性。

为了避免这种情况,我计划添加一些指向 struct 的虚拟指针,以便将来使用。

struct S{
   int  aVar1;
   void *ptr1;
   void *dummyptr1;
   void *dummyptr2;
   void *dummyptr3;
   void *dummyptr4;
   void *dummyptr5;
   void *dummyptr6;
 }

请有更好的解决方案来保持向后兼容性?

【问题讨论】:

  • 更好的解决方案是不要期望结构的大小在实际发生变化时永远不会改变
  • 客户认为他们从sizeof(struct S)获得了哪些信息?
  • 您希望在何种意义上保持兼容性?你能举一个兼容性变得重要的例子吗?您应该知道,根据标准严格来说,S 的上述定义都不兼容(因此您必须考虑工具链/平台的细节)。
  • 他们为什么要依赖 sizeof 结构?实际上依赖ABI没有改变吗?他们没有重新编译(你正在编写一个库)吗?你在传递信息吗?工厂可以工作吗?使用版本号序列化/反序列化?这取决于...
  • 粉刺可行吗?将新成员隐藏在不透明指针后面,类似于 [Qt's d-pointer](wiki.qt.io/D-Pointer)

标签: c++ c backwards-compatibility


【解决方案1】:

不要这样做。

希望现有成员保持当前的填充安排,将新成员添加到结构中甚至是不安全的。 C 和 C++ 标准都没有在这方面做出任何保证。

唯一安全的方法是从头开始构建新结构并添加新的 API 函数。

【讨论】:

  • 但是在 C++ 中,如果您通过继承添加成员,则可以保证保留布局。
  • @skyking 是的,这是真的。
  • 这有点极端...是的,C 标准不做任何保证,但我们并不总是针对“仅”标准,而是针对特定平台,以及我所知道的几乎所有平台都提供明确的 ABI 保证使二进制兼容性成为可能并定期完成。
  • @MatteoItalia 是的,但为此您/我们需要知道您的目标平台/工具链,否则您只能依赖标准规定的内容。请注意,如果您实际上不需要针对特定​​平台/工具链,通常是一个坏主意 - 我建议您在辞职使用平台/工具链特定解决方案之前尝试找到可移植的解决方案。通常这是可能的,而且不会太难。
【解决方案2】:

Afaik,C 的做法是使用扩展,如下所示:

struct A{
  int data;
  void* extension;
};

然后,在需要时添加扩展并使用扩展指针将其与原始A 链接。

struct A_ext1{
  int ext_data;
  void* extension;
};

A a;
A_ext1 a_ext1;
a.extension = &a_ext1;

等等...这将创建一个令人讨厌的“分层”结构结构。这样可以确保您的原始结构永远不会改变,因此使用旧接口的客户端在更改后将保持兼容,而无需重新编译。

这里重要的是跟踪界面的版本 - 每个新扩展都是新版本。十个你的客户需要知道他们支持的版本,所以他们只知道和支持扩展直到他们知道的版本。此外,您需要确保不要将此类结构的所有权传递给客户端。他们不知道可能有多少层扩展,因此他们无法正确地破坏整个事物。

当然,您也可以尝试 C++ 方法并仅使用继承,创建从旧版本继承的新版本 struct。我不确定后一种方法的含义,但它也应该有效。

【讨论】:

    【解决方案3】:

    如果它是 c++,您可以编写从旧结构派生的新结构。通过这样做,您可以在旧函数中使用新结构,并在新结构中使用新函数。

    【讨论】:

      【解决方案4】:

      使用“装饰器模式”专门解决了这个问题。它只是允许您使用组合扩展现有类(在您的情况下为结构)的功能,而无需更改其结构。您只需创建一个新结构(或类),并将旧结构作为新结构中的成员。然后,您将根据需要向这个新结构添加新功能。更多信息here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        相关资源
        最近更新 更多