Constructor Invocation Sequence
When instantiating an object T obj;, any constructor (trivial or non-trivial) will be invoked.
- Members in initialization lists are initialized in declaration order
- Members absent from initialization lists with default constructors trigger automatic invocation
- Virtual table pointers (vptrs) must be initialized before base constructors
- Base class constructors execute in declaration order (independent of initialization list order):
- Explicit parameters passed if base listed
- Default constructor invoked if unlisted
thispointer adjusted for subsequent base classes
- Virtual base constructors initialize depth-first from left to right
Object Composition Example
class Point {
public:
Point(float xval = 0.0f, float yval = 0.0f);
virtual ~Point();
private:
float x_, y_;
};
class LineSegment {
Point start_, end_;
public:
LineSegment(const Point& a, const Point& b)
: start_(a), end_(b) {}
};
// Constructor expansion
LineSegment* LineSegment::LineSegment(LineSegment* self,
const Point& a,
const Point& b) {
self->start_.Point::Point(a);
self->end_.Point::Point(b);
return self;
}
Virtual Inheritance Mechanics
Virtual base classes require specialized handling:
class Point3D : virtual public Point {
public:
Point3D(float x, float y, float zval)
: Point(x, y), z_(zval) {}
private:
float z_;
};
// Constructor with virtual base control
Point3D* Point3D::Point3D(Point3D* self, bool is_derived,
float x, float y, float z) {
if(is_derived) self->Point::Point();
self->__vptr_Point3D = __vtable_Point3D;
self->z_ = z;
return self;
}
Vptr Initialization Sequence
Virtual pointers initialize after base construction but before user code:
- Invoke virtual and direct base constructors
- Initialize vptrs to correct virtual tables
- Expand member initialization lists
- Execute programmer-defined constructor body
Sample expansion:
PVertex* PVertex::Constructor(PVertex* self, bool is_derived,
float x, float y, float z) {
if(is_derived) self->Point::Point();
self->Vertex3D::Vertex3D(x,y,z);
self->__vptr_PVertex = __vtable_PVertex;
// User code executes after vptr setup
if(debug)
cerr << "Size: " << self->__vptr_PVertex[3].func(self);
return self;
}
Critical considerations:
- Vptrs must initialize before any virtual function calls
- Member functions in initialization lists are unsafe for data access
- Virtual calls in base initialization contexts risk undefined behavior