Consider the following virtual inheritance:
classPoint3D: Public Virtualpoint{Point3D (floatx =0.0,floaty =0.0, Flloat z =0.0):P oint (x, y). _z (z) {} pooint (ConstPoint3D &RHS):P oint (RHS), _z (rhs._z) {} Point3D&operator=(Constpoint3d&); ~Point3D (); Virtual floatZ () {return_z;}protected: float_z;};
The traditional constructor expansion phenomenon is not used because of the sharing of virtual base class:
//illegal constructor expansion of contentpoint*Point ::P oint (Point3D* This, floatXfloatYfloatz) { //Personal management personal structure and destruction notes This-Point ::P oint (x, y); This->__vptr_point3d =__vtbl_point3d; This->__vptr_point3d__point =__vptr_point3d__point; This->_z =rhs._z; return This;}
Can you find out what's wrong with the Point3D constructor extensions above?
This, my understanding is the diamond inheritance, Subobject is not responsible for calling the constructor of the bottom class, the calling class should be the diamond bottom of the close relatives married class, so the extension code should not have to point constructor Call. I would also like to share with you your views on this expansion code. The specific reasons for my view are as follows:
Consider the following three derivation scenarios:
class Virtual Public point{...}; class Public Public vertex{...}; class Public Vertex3d{...};
The Vertex constructor must also invoke the constructor of point. However, when Point3D and Vertex are Vertex3d subobjects, their invocation of point constructor cannot occur, instead of a bottom class, Vertex3d is responsible for Poin T is initialized and then inherited by Pvertex to complete the construction of the shared point subobject.
Do not initialize the virtual base class now, as this leads to more additions to constructor that indicate that the virtual base class constructor should not be called. The constructor function itself must thus conditionally test the passed in parameters and then decide not to call the relevant virtual base class constructors. Here's what Point3D's constructor expands:
point3d*Point3D::P Oint3d (Point3D* This,BOOL__most_derived,floatXfloatYfloatz) { if(__most_derived! =flase) { This-Point ::P oint (x, y); } This-__vptr_point3d =__vtbl_point3d; This->__vptr_point3d__point =___vtbl_point3d__point; This->_z =rhs._z; return This;}
In deeper cases, such as Vertex3d calls Point3D and Vertex constructor, the __most_derived parameter is always set to false, thus suppressing two constructors The invocation operation of the constructor.
//constructor extensions in the case of virtual base classvertex3d*Vertex3d::vertex3d (Vertex3d* This, bool__most_derived,floatXfloatYfloatz) { if(__most_derived! =false){ This-Point ::P oint (x, y); } //not the lowest class, only picking. This->point3d::P Oint3d (false, x, Y, z); This->vertex::vertex (false, x, y); //Set Vptrs//inserting user code return This;}
Adopting such a strategy ensures that the semantics are correct, when we define Point3D origin; , Point3D constructor can correctly invoke its point virtual base class Subobject, and when we define VERTEX3D CV, Vertex3d constructor correctly calls point Constructor. The constructors of Point3D and Vertex do things other than the call to point.
Many people may have noticed a state in which the virtual base class constructors is called with a clear definition: it will only be called when a complete class object is defined; If object is just a subobject of a complete object, it will not be called.
With this as leverage, we can produce more efficient constructors. Some compilers split each constructor into two, one for the complete object and the other for subobject. Complete object version unconditional call to virtual base constructors, set all the vptrs and so on; The subobject version does not call virtual base constructors and vptrs. I'd like to discuss Vptrs's settings in the next blog post. Constructor splits can bring speed, but it's up to you to judge whether the compiler you're using supports this feature.
Virtual Inheritance (Vsan inheritance)