是否可以在不重新编译客户端代码的情况下扩展虚拟接口?

发布于 2024-11-02 05:44:48 字数 119 浏览 3 评论 0原文

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

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

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

A library provides a class with virtual functions. Can this class be extended with new virtual functions without recompiling binaries dynamically linked to the library?

I beleive this is not possible in standard. Are there platforms allowing this?

Would that be easier if new functions are only added to the end of the class body?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温馨耳语 2024-11-09 05:44:48

该标准不关心二进制兼容性。它与类有关,并且通过将类的定义从一个翻译单元“更改”为另一个翻译单元,您确实会调用未定义的行为。

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

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

当你创建一个带有虚函数的类时,你会得到一个如下所示的虚表:

// 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 函数时code>B 你会调用 DN+1 函数,它甚至可能没有相同的参数......哎呀!

不过,如果您知道没有派生类添加其自己的任何虚函数,那么这是可以完成的。

The standard is not concerned with binary compatibility. It is concerned though with classes, and by "changing" the definition of a class from one translation unit to another you indeed invoke undefined behavior.

Most compilers do allow a number of changes without the need for recompilation, however the list is small... and for this one I would say that it might not be possible, depending on the a priori knowledge of the derived classes.

The problem I foresee lies with the optimization that compilers usually carry out on the virtual tables.

When you create a class with virtual functions, you get a virtual table that looks like so:

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

In order to gain some space, the derived class own virtual functions are usually "appended":

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

This way a D object only has one virtual pointer, than can be used as such even when the type is (statically) a B (through pointer or reference).

However, if you were to extend B without recompiling D, then it would just plain crash, since when calling the N+1 function of B you would instead call the N+1 function of D which would probably not even have the same arguments... oups!

It can be done, though, if you know than no derived class add any virtual function of its own.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文