C++使用抽象类无需 pimpl 即可实现 abi 兼容性
假设我有一个类 B_Impl
,它继承并实现了一个纯抽象类 B
(不包含任何数据字段)。
假设类 A
仅通过 B*
使用 B_Impl
。
如果我向 B_Impl.h
添加一个字段(显然,A
中未包含该字段),是否会保留 ABI 兼容性?
我想,它不会被保留,--阅读 https://wiki.qt.io/ 后D 指针。
但我可以在我的应用程序中看到,更改 B_Impl.h
后,A
类的目标文件不会重新生成,并且一切仍然正常工作。
也许,这是因为在我的应用程序中 A
和 B
是同一个应用程序的一部分,而 B
不是 A 调用的库?或者是因为
vtable
始终位于内存中的第一个字段,并向 B_Impl.h
添加另一个字段(位于“B”之下) code>) 不会改变
vtable
是第一个字段的事实吗?或者这个东西是由链接器以某种方式纠正的,而不是通过重新生成 A
-object-file 来纠正的?
老实说,我在这里有点困惑:
这个 ABI 问题仅与库有关吗?
当我调用
B*
并通过更改B_Impl.h
获得一些段错误时,如何调整应用程序中的情况(其中 A 使用 B 不作为库) code>,(即忽略文章中建议的 Pimpl 原则),并且不重新生成A
-object-file?或者,如果我通过接口
B*
使用一个类,我可以通过添加新字段等来尽可能多地更改它的B_Impl.h
,并且不用担心我必须直接在同一个应用程序中重新编译使用B
的A
或重新编译使用C
>B 作为对共享库的调用?感谢您的关注!
Suppose I have a class B_Impl
which inherits and implements a pure abstract class B
(not containing any data-fields).
Suppose class A
uses B_Impl
via B*
only.
If I add a field to B_Impl.h
(clearly, not included by A
), will ABI compatability be preserved?
I thought, that it will not be preserved, -- after reading https://wiki.qt.io/D-Pointer.
But I can see in my app that after changing B_Impl.h
, the object file for class A
is not regenerated and everything still works great.
Maybe, this is because in my app A
and B
are part of the same app and B
is not a library called by A
? Or is it because vtable
is located as the very first field in the memory always and adding another field to B_Impl.h
(which is "beneath" B
) does not change the fact that vtable
is the first field? Or is this stuff somehow corrected by the linker rather than by re-generating A
-object-file?
Honestly, I am a bit confused here:
Is this ABI problem is only about libraries?
How can I modulate the situation in my app (where A uses B not as a library) when I call
B*
and get some seg-fault by changingB_Impl.h
, (i.e. by ignoring the Pimpl principle, suggested in the article), and not re-generatingA
-object-file?Or is it true that if I use a class via interface
B*
I can change itsB_Impl.h
as much as I could by adding new fields etc. and not being afraid that I will have to re-compileA
that usesB
directly in the same app or re-compileC
that usesB
as a call to a shared library? Thank you for attention!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的。如果翻译单元不包含
B_Impl
的定义,则对B_Impl
的更改不会影响兼容性。接口兼容性 - 无论是 API 还是 ABI - 仅在使用接口时才重要。在您的示例中,使用了
B
的接口;不是B_Impl
的接口。B_Impl
是否在库中并不重要。Yes. If a translation unit doesn't include the definition of
B_Impl
, then changes toB_Impl
won't affect the compatibility.The interface compatibility - whether it is API or ABI - matters only when the interface is used. In your example, the interface of
B
is used; not the interface ofB_Impl
.Whether
B_Impl
is in a library or not shouldn't matter.