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

Kir*_*rov 9 c++ enums gcc binary-compatibility

我知道添加static成员函数很好,但enum定义怎么样?没有新的数据成员,只是它的定义.


一点背景:

我需要添加一个static成员函数(在类中),它将IP通过其字符串表示来识别(函数)地址的版本.的第一件事,是在我脑海中是申报enumIPv4,IPv6并且Unknown,使这个enum我函数的返回码.

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

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


编辑:关于@PeteKirkham的评论:好的,至少 - 有没有办法测试/检查更改的ABI,或者最好发布有关它的新问题?

EDIT2:我刚刚发现了一个SO问题:静态分析工具来检测C++中的ABI中断 .我认为它在某种程度上与此相关,并回答了关于检查二进制兼容性的工具的部分.这就是我在这里联系它的原因.

Mat*_* M. 6

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

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

虽然这仍然可能会破坏ABI,但实际上需要一个有趣的编译器.

至于ABI破损:

  • 修改类的大小:添加数据成员,除非你设法将它们存入以前未使用的填充(当然是编译器特定的)
  • 修改类的对齐:更改数据成员,有人工膨胀对齐(联合)的技巧,但放气它需要编译器特定的编译指示或属性和兼容的硬件
  • 修改vtable的布局:添加虚拟方法可能会更改vtable中先前虚拟方法的偏移量.对于gcc,vtable按声明的顺序排列,因此在最后添加虚方法有效...但是它不能在基类中工作,因为vtable布局可以与派生类共享.最好考虑冷冻
  • 修饰函数的签名:符号的名称通常取决于函数本身的名称及其参数的类型(加上方法的类名和方法的限定符).您可以const在参数上添加顶级,无论如何都会被忽略,您通常可以更改返回类型(这可能会带来其他问题).请注意,添加具有默认值的参数破坏ABI,就签名而言,将忽略默认值.最好考虑冷冻
  • 删除以前导出符号的任何函数或类(即具有直接或继承虚拟方法的类)

我可能已经忘记了一两点,但这应该让你已经有一段时间了.

ABI的例子:Itanium ABI.


Jam*_*nze 5

正式...如果您链接的文件是针对您的类的两个不同版本编译的,那么您违反了一个定义规则,即未定义的行为.实际上......关于破坏二进制兼容性的唯一事情是添加数据成员或虚函数(非虚函数很好),或更改函数的名称或签名,或涉及基类的任何事情.这似乎是普遍的 - 我不知道规则不同的编译器.