C++ 在类中添加枚举定义会破坏其二进制向后兼容性吗?

C++ 在类中添加枚举定义会破坏其二进制向后兼容性吗?,c++,gcc,enums,binary-compatibility,C++,Gcc,Enums,Binary Compatibility,我知道添加静态成员函数很好,但是枚举定义如何?没有新的数据成员,只是它的定义 一点背景: 我需要添加一个静态成员函数(在类中),该函数将通过其字符串表示形式识别(该函数)IP地址的版本。我想到的第一件事是为IPv4、IPv6和Unknown声明enum,并使此enum返回函数的代码 但我不想破坏二进制向后兼容性 一个非常糟糕的问题(对于SO来说)-这里有什么来源或问题吗,我可以阅读更多关于这方面的内容吗?我的意思是-什么破坏了二进制兼容性,什么没有。或者它取决于很多东西(比如体系结构、操作系统

我知道添加
静态
成员函数很好,但是
枚举
定义如何?没有新的数据成员,只是它的定义


一点背景:

我需要添加一个
静态
成员函数(在类中),该函数将通过其字符串表示形式识别(该函数)IP地址的版本。我想到的第一件事是为
IPv4
IPv6
Unknown
声明
enum
,并使此
enum
返回函数的代码

但我不想破坏二进制向后兼容性

一个非常糟糕的问题(对于SO来说)-这里有什么来源或问题吗,我可以阅读更多关于这方面的内容吗?我的意思是-什么破坏了二进制兼容性,什么没有。或者它取决于很多东西(比如体系结构、操作系统、编译器等等)


编辑:关于@PeteKirkham的评论:好吧,至少-有没有办法测试/检查是否有变化,或者最好发布新的问题


EDIT2:我刚找到一个。我认为这在某种程度上与此相关,并回答了关于检查二进制兼容性的工具的部分。这就是为什么我在这里把它联系起来。

这里真正的问题显然是为什么让它成为类(静态)成员

从定义中可以明显看出,这完全可以是它自己的名称空间(可能是头文件)中的一个自由函数,或者如果使用是隔离的,则可以在源文件中的匿名名称空间中定义

尽管这仍然有可能破坏ABI,但这确实需要一个有趣的编译器来完成

至于ABI破损:

  • 修改类的大小:添加数据成员,除非您设法将它们隐藏到以前未使用的填充中(当然,特定于编译器)
  • 修改类的对齐方式:更改数据成员,有一些技巧可以人为地扩大对齐方式(联合),但缩小对齐方式需要编译器特定的杂注或属性以及兼容的硬件
  • 修改vtable的布局:添加虚拟方法可能会更改vtable中以前虚拟方法的偏移量。对于gcc,vtable是按照声明的顺序排列的,因此在最后添加virtual方法是可行的。。。但是,它在基类中不起作用,因为vtable布局可能与派生类共享最好考虑冷冻
  • 修改函数签名:符号的名称通常取决于函数本身的名称及其参数的类型(对于方法,加上类的名称和方法的限定符)。您可以在参数上添加顶级的
    const
    ,它无论如何都会被忽略,您通常可以更改返回类型(但这可能会带来其他问题)。请注意,添加带有默认值的参数会破坏ABI,就签名而言,默认值将被忽略最好考虑冷冻
  • 删除以前导出符号的任何函数或类(即具有直接或继承虚拟方法的类)
我可能忘记了一两点,但这应该会让你坚持一段时间


ABI是什么的示例:.

正式。。。如果您链接根据两个不同的 在类的版本中,您违反了一个定义规则 是未定义的行为。实际上。。。关于唯一破碎的东西 二进制兼容性是指添加数据成员或虚拟函数 (非虚拟函数也可以),或者更改 函数或任何涉及基类的内容。这似乎是 通用-我不知道编译器的规则在哪里
不一样

可能不是,但完全依赖于编译器。C++标准不涉及二进制对象格式。好,然后添加<代码> GCC < /Cord>标签。我知道,这个标准并没有说明任何问题,但我认为这可能还有另一个标准,这与“代码> ABI < /代码>或某事有关:”KIILL:ABI将由C++实现或特定平台的供应商定义,或者两者的某种组合来定义。最好尽可能地使用特定于平台的ABI,因为在同一平台上不同的C++实现至少有机会产生链路兼容二进制文件。然而,有些事情总是实现特定的,例如标准库类的大小和布局,这就是为什么实现不必甚至与自身兼容(调试与非调试),即使遵循相同的C++ ABI。所以对于给定的平台,C abi通常比任何C++ abi更安全。它更小,如果他们想能够链接到平台的系统调用之类的东西,那么在
extern“C”
中实现就必须遵循它。@SteveJessop-啊,这让我更困惑了。你知道什么好的消息来源吗,我能读到更多的信息吗?我对这类事情一点也不熟悉,显然,我真的需要做点什么:)谢谢!好吧,如果我使这个函数
静态
,它将完全适合当前整个包装器的设计(对于任何类型的套接字传输)。另外,据我所知,对于
gcc
,这不会破坏二进制兼容性。因此,添加
enum
定义不会破坏它,对吗?哈,谢谢你的链接,它看起来很棒:)但是有没有办法检查破坏的ABI?某种工具或什么的?@KirilKirov:不幸的是,我不知道任何工具。
enum
声明和
static
函数不应破坏任何sane编译器的ABI。我可以担保gcc和Clang:)是的,“未定义的行为”让我感到害怕,因为这一变化发生在一个核心库中,用于许多应用程序。谢谢你的回复