可以扩展虚拟接口而无需重新编译客户端代码吗?

时间:2011-04-19 08:36:18

标签: c++ shared-libraries virtual-functions binary-compatibility

库提供了一个具有虚函数的类。可以使用新的虚函数扩展此类,而无需重新编译动态链接到库的二进制文件吗?

我相信这在标准中是不可能的。有平台允许吗?

如果只将新函数添加到类主体的末尾会更容易吗?

1 个答案:

答案 0 :(得分:5)

该标准不涉及二进制兼容性。它关注的是类,并且通过将类的定义从一个翻译单元“改变”到另一个翻译单元,你确实会调用未定义的行为。

大多数编译器都允许进行大量更改而无需重新编译,但是列表很小......对于这个,我会说这可能是不可能的,取决于先验知识。派生类

我预见到的问题在于编译器通常在虚拟表上执行的优化。

使用虚函数创建类时,会得到一个如下所示的虚拟表:

// B virtual table
0 - Offset to complete object
1 - RTTI
2 - func0
3 - func1
...

为了获得一些空间,派生类自己的虚函数通常是“附加”:

// D virtual table
Same as B
N+3 - func(N+1)
N+4 - func(N+2)

这样一个D对象只有一个虚拟指针,即使该类型(静态地)为B(通过指针或引用),也可以这样使用。

但是,如果你在不重新编译B的情况下扩展D,那么它就会崩溃,因为在调用N+1的{​​{1}}函数时你会调用它B的{​​{1}}函数甚至可能没有相同的参数... oups!

但是,如果你知道而不是派生类添加任何自己的虚函数,那么可以这样做。