I was working the last 5 years with the assumption that virtual inheritance breaks static composition.
But now I discovered, that static composition is still maintained, there is just additional information about the location of the correct instance. Is this right?
Objects of classes that use virtual inheritance have a fixed memory layout that is determined in compilation time. Accessing the virtual base however requires a level of indirection since you cannot tell where it is relative to the derived pointer.
See Wikipedia
Data Layout in non-virtual Inheritance:
Point2d:
Point3d:
Point3d is statically composed of Point2d and the member of Point3d.
Under virtual inheritance
Implemented with an offset variable inside the object.
Point3d:
Accessing
Point3d* point3d->x_
in this context will be translated to (C++ Pseudocode):Note that there are different ways to implement virtual inheritance like offset pointers inside the vtable, this is just one way to implement virtual inheritance. I chose this one because indirection via vtables would require more ascii drawing.
Virtual inheritance has no benefit here and I would expect (as @Matthieu noted in the comments) a compiler to optimize this class so that it's internal data layout is the same as in non-virtual inheritance. Virtual inheritance is only beneficial in multiple inheritance (see
Vertex3d
class below).How does this look like in multiple inheritance?
Vertex:
Vertex3d:
In virtual multiple inheritance both base classes
Vertex
andPoint3d
share the basePoint2d
inVertex3d
. non-virtual inherited members are layed out as usual.The point of virtual multiple inheritance is that all descendants of
Point3d
andVertex
will share one copy ofPoint2d
. Without virtual multiple inheritance (= "ordinary" multiple inheritance) both thePoint3d
subobject and theVertex
subobject ofVertex3d
would have its own copy ofPoint2d
:Layout of
Vertex3d
without virtual multiple inheritance:References:
Maybe I'm dumb, but I don't understand what you mean by "static composition." You say pimpl breaks it, so let's start with that and take polymorphism and virtual inheritance out of it.
Suppose you have this code:
When you say "breaks static composition" do you mean the
sizeof
things change as you change out the pimpl in the interface?