Never change the size of an exported cpp class:
In summary, never ever change the size or layout (don’t move the data around) of exported (i.e visible to the user) C++ classes once your library has been released. A C++ compiler generates code assuming that the size or the ordering of data in a class does not change after the application has been compiled.
Never add an var to class. It may crash with new version
The trick is to keep the size of all public classes of a library constant by only storing a single pointer. This pointer points to a private/internal data structure that contains all the data. The size of this internal structure can shrink or grow without having any side-effect on the application because the pointer is accessed only in the library code and from the application’s point of view the size of the object never changes – it’s always the size of the pointer. This pointer is called the d-pointer.
benefits of d-pointer
It’s not all about binary compatibility. The d-pointer has other benefits:
- Hide implementation details – We can ship libraries with just the header files and the binaries. The .cpp files can be closed source.
- The header file is clean of implementation details and can serve as the API reference.
- Since the header files needed for implementation are moved from the header file into the implementation (source) file, compiles are much faster.
It is indeed true that the above benefits appear trivial. The real reason to use d-pointers in Qt is for binary compatibility and the fact that Qt started out closed source.
So far, we have only seen the d-pointer as a C-style data structure. In reality, it contains private methods (helper functions).
LabelPrivate might have a
getLinkTargetFromPoint() helper function that is required to find the link target when the mouse is clicked.
In many cases, these helper methods require access to the public class i.e some functions from Label or from its base class Widget. For example, a helper method,
setTextAndUpdateWidget() might want to call
Widget::update() which is a public method to schedule a redraw the Widget. So, the
WidgetPrivate stores a pointer to the public class called the q-pointer.
d-pointers in Qt
In Qt, practically every public class uses the d-pointer approach. The only cases where it’s not used is when it is known in advance that the class will never ever have extra member variables added to it. For example, for classes like
QRect, no new members are expected to be added and hence the data members are stored straight into the class itself instead of using the d-pointer.