接口(抽象类)与其他虚拟更改的 ABI 兼容性
即使在派生类中进行了涉及虚拟的其他更改,类视图的 ABI 是否仍保持稳定?
也就是说,假设我有一个接口InterfaceA(具有许多纯虚函数的抽象类)和一个从它继承的类DerivedB。我编写了一个库,其中有一个采用 InterfaceA *
的函数。我想知道的是,只要接口本身不改变,接口是否保持二进制兼容。
显然,如果我修改 InterfaceA
我不希望代码是二进制兼容的。但是,如果我只是修改 DerivedB
,假设我继承了更多接口或添加其他虚拟函数,该怎么办?在最极端的情况下,我从定义 InterfaceA
的另一个类中进行多重继承。尽管进行了所有这些更改,InterfaceA
是否仍保持二进制兼容?
到目前为止,我的假设和经验是,它是兼容的。我只是在寻找对此的确认(如果不兼容则进行反驳)。
注意:我不关心动态类型或其他转换,我只关心接口函数本身。
另请注意:假设正在使用的编译器版本整体上是 ABI 稳定的 --没有重大版本更改。
Does the ABI of the view of a class remain stable even if other changes, involving virtuals, are made in the derived class?
That is, say I have an interface InterfaceA
(abstract class with many pure virtual functions) and a class DerivedB
that inherits from it. I write a library that has a function taking a InterfaceA *
. What I want to know is whether the interface remains binary compatible so long as the interface itself does not change.
Clear, if I modify InterfaceA
I do not expect the code to be binary compatible. However, what if I just modify DerivedB
, say I inherit more interfaces or add other virtual functions. In the most extreme say I multiply inherit from another class which defines InterfaceA
. Does InterfaceA
remain binary compatible despite all these changes?
My assumption, and experience, to now is that yes it is compatible. I'm just looking for confirmation of this (or refutation if not compatible).
Note: I don't care about dynamic typing, or other casting, I only care about the interface functions themselves.
Also Note: Assume the compiler versions being used are ABI stable as whole -- no major version changes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,只要 InterfaceA 中的虚函数的名称、参数和顺序不改变,它就会保持二进制兼容。请注意,这允许您在类声明的末尾添加函数。
(C++ 规范可能没有明确保证这一点,但 COM 依赖于此,因此大型 C++ 编译器将以这种方式工作。)
Yes, as long as the name, arguments, and order of virtual functions in InterfaceA does not change, it will stay binary compatible. Note that this allows you to add functions at the end of the class declaration.
(It is possible this is not explicitly guaranteed by the C++ spec, but COM relies on this so the big C++ compilers will work this way.)
假设您没有跨 ABI 边界使用 DeriveddB,您应该能够做任何您想做的事情。纯虚拟类 (DerivedA) 是最重要的,如果您不更改它,那么您是对的 - 任何使用该指向 InterfaceA 的指针都不会出现任何跨越边界的问题。
事实上,您甚至可以将函数添加到 InterfaceA 的末尾,只要它是叶接口(即没有其他接口继承自它)并且该函数不是另一个函数的重载。当然,它需要遵循与其他函数相同的“ABI 规则” - 即参数类型必须是原始类型或指向其他接口的指针等。如果您有版本控制系统,您的应用程序可以检查插件的版本并确定是否或者不能安全地调用新函数 - 因此为较新的插件添加功能,但在更改之前编译的旧插件仍然可以工作。很酷!
Assuming you're not using DerivedB across the ABI boundary, you should be able to do just about anything you want to it. The pure virtual class (DerivedA) is what matters most and if you're not changing it then you're correct - anything using that pointer to InterfaceA won't have any problems crossing the boundary.
In fact, you can even add a function to the end of InterfaceA as long as it is a leaf interface (ie no other interfaces inherit from it) and the function isn't an overload of another function. Of course it needs to follow the same "ABI rules" as your other functions - ie the parameter types must be primitive types or pointers to other interfaces, etc. If you have a versioning system, your app can check the plugin's version and determine whether or not the new function can be safely called - thus adding functionality for newer plugins but old plugins compiled before the change will still work. Pretty cool!