2011-09-13 33 views
3

即使在派生类中进行涉及虚拟的其他更改,类视图的ABI是否仍然保持稳定?接口(抽象类)与其他虚拟更改的ABI兼容

也就是说,我有一个接口InterfaceA(具有许多纯虚函数的抽象类)和一个继承自它的类DerivedB。我写了一个函数库,它的功能是InterfaceA *。我想知道的是,只要接口本身没有改变,接口是否保持二进制兼容。

清除,如果我修改InterfaceA我不认为代码是二进制兼容的。但是,如果我只是修改DerivedB,说我继承更多接口或添加其他虚拟功能。在最极端的说法中,我从另一个定义InterfaceA的类继承了多个继承。尽管所有这些变化,InterfaceA仍然保持二进制兼容?

我的假设和经验到现在是,它是兼容的。我只是寻找这个确认(或反驳,如果不兼容)。

注意:我不关心动态打字或其他投射,我只关心界面功能本身。

另请注意:假设正在使用的编译器版本是ABI稳定的整体 - 没有主要的版本更改。

+2

可能[this](http://accu.org/index.php/journals/1718)这篇文章对你很有意思。 – Simon

回答

3

是的,只要InterfaceA中虚拟函数的名称,参数和顺序没有改变,它就会保持二进制兼容。请注意,这允许您在类声明的末尾添加函数。

(这有可能是不明确的C++规范保证,但COM依赖于这个如此大的C++编译器会以这种方式工作。)

+0

我认为你对规范是正确的:它对ABI甚至图书馆都很沉默。我正在使用GCC。如果一个重载的虚拟函数(同名)被添加到接口的末尾会怎么样? –

+0

这不应该破坏二进制兼容性。 –

+0

根据这里的答案:http://stackoverflow.com/questions/14875052/pure-virtual-functions-and-binary-compatibility,在接口的末尾添加虚拟功能将无法在MSVC上工作。 – Eugene

0

你不跨越ABI边界使用DerivedB假设,你应该可以做任何你想做的事情。纯虚拟类(DerivedA)是最重要的,如果你不改变它,那么你是正确的 - 任何使用指向InterfaceA的指针都不会有任何跨越边界的问题。

事实上,你甚至可以在InterfaceA的结尾添加一个函数,只要它是一个叶子接口(即没有其他接口继承它),并且该函数不是另一个函数的重载。当然,它需要遵循与其他函数相同的“ABI规则” - 即参数类型必须是原始类型或指向其他接口的指针等。如果您有版本控制系统,您的应用程序可以检查插件的版本并确定是否或者不能安全地调用新函数 - 从而为新插件添加功能,但在更改之前编译的旧插件仍然可以工作。很酷!