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 changing B_Impl.h
, (i.e. by ignoring the Pimpl principle, suggested in the article), and not re-generating A
-object-file?
Or is it true that if I use a class via interface B*
I can change its B_Impl.h
as much as I could by adding new fields etc. and not being afraid that I will have to re-compile A
that uses B
directly in the same app or re-compile C
that uses B
as a call to a shared library? Thank you for attention!
If I add a field to B_Impl.h (clearly, not included by A), will ABI compatability be preserved?
Yes. If a translation unit doesn't include the definition of B_Impl
, then changes to B_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 of B_Impl
.
Is this ABI problem is only about libraries?
Whether B_Impl
is in a library or not shouldn't matter.