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.