What Is the Order of Construction of Derived Classes?

Creating one derived object runs more than one constructor. C++ builds the object in layers, from the top of the inheritance tree downward: the most-base class is constructed first, then each class below it in turn, and the most-derived class is constructed last.

That single sentence answers most questions about construction order, but it hides a detail worth pulling apart. The constructor you call is the derived one. The constructor whose body finishes first is the base one. This lesson works through the mechanism behind that inversion, extends it to chains of any depth, and finishes with what happens when the object is destroyed.

A Derived Object Contains a Base Subobject

Inheritance does not copy members from the base class into the derived class. A derived object is one block of memory that physically contains a complete base class object, called the base subobject, alongside the members the derived class declares for itself.

#include <iostream>

class Instrument
{
public:
    int m_serial {};
};

class Keyboard : public Instrument
{
public:
    int m_keyCount {};
};

int main()
{
    std::cout << "An Instrument occupies " << sizeof(Instrument) << " bytes\n";
    std::cout << "A Keyboard occupies " << sizeof(Keyboard) << " bytes\n";

    return 0;
}
An Instrument occupies 4 bytes
A Keyboard occupies 8 bytes

A Keyboard is twice the size of an Instrument because it carries an entire Instrument inside it plus its own m_keyCount. Think of the object as two parts stacked together: the Instrument part and the Keyboard part. Construction order is really a question about which of those two parts gets initialized first.

Key Insight
A derived class object is a two-part object: one part for each base class it inherits, and one part for the members it declares itself. The base part is a real object embedded in the derived one, not a copy of the base class's fields.

The Base Layer Finishes Before the Derived Constructor Body Starts

Since the base subobject is a genuine object, it needs a genuine constructor call. C++ makes that call before the derived constructor gets to run any of its own code, which means the derived constructor body can rely on every base member already holding its final value.

#include <iostream>

class Instrument
{
public:
    int m_serial {};

    Instrument()
        : m_serial { 4021 }
    {
        std::cout << "Instrument subobject done, serial " << m_serial << '\n';
    }
};

class Keyboard : public Instrument
{
public:
    int m_keyCount {};

    Keyboard()
        : m_keyCount { 88 }
    {
        std::cout << "Keyboard body starts, serial already reads " << m_serial << '\n';
    }
};

int main()
{
    Keyboard upright {};
    std::cout << "upright has " << upright.m_keyCount << " keys\n";

    return 0;
}
Instrument subobject done, serial 4021
Keyboard body starts, serial already reads 4021
upright has 88 keys

Only one object was created here, and two constructors ran to build it. Notice the second line: by the time Keyboard's body executes, m_serial is already 4021. That is the practical payoff of the ordering. A derived class routinely reads and calls into its base, while the base knows nothing about its derived classes, so the only ordering that is safe for both is base first.

Reverse the order and the derived constructor would be reading base members that had not been initialized yet, which is undefined behavior waiting to happen. Building the parent before the child is also the only order that makes sense conceptually, since a child cannot exist without a parent.

The Four Stages Inside a Single Constructor

"Base first" is the headline, but a constructor for a derived class actually moves through four stages. Watching them in order explains where member variables of the derived class fit in.

  1. Memory for the whole object, base part and derived part together, is set aside.
  2. The base subobject is constructed by a base class constructor.
  3. The derived class's own data members are initialized, in the order they are declared in the class.
  4. The derived constructor's body finally runs.

This program gives each stage a voice by making the member types print during their own construction.

#include <iostream>

class Tuner
{
public:
    Tuner() { std::cout << "  tuner member\n"; }
};

class Dampers
{
public:
    Dampers() { std::cout << "  damper member\n"; }
};

class Instrument
{
public:
    Instrument() { std::cout << "  Instrument subobject\n"; }
};

class Keyboard : public Instrument
{
public:
    Tuner m_tuner {};
    Dampers m_dampers {};

    Keyboard() { std::cout << "  Keyboard constructor body\n"; }
};

int main()
{
    std::cout << "about to build a Keyboard\n";
    Keyboard upright {};
    std::cout << "Keyboard is ready\n";

    return 0;
}
about to build a Keyboard
  Instrument subobject
  tuner member
  damper member
  Keyboard constructor body
Keyboard is ready

The base subobject is complete before m_tuner exists, and both members are complete before a single statement of the Keyboard body executes.

Warning
Members are initialized in declaration order, not in the order you list them in the member initializer list. Writing them out of order in the list does not change what actually happens, and GCC will report it with a -Wreorder warning. Keep the initializer list in the same order as the declarations so the code reads the way it runs.

Which Base Constructor Runs?

Stage 2 raises an obvious question: a base class can have several constructors, so which one does C++ pick? Unless the derived class says otherwise, it picks the base class's default constructor. Every example above relies on that: none of the derived classes mention their base at all, so the base default constructor is selected automatically.

Two consequences follow. First, a base class whose members are all sensibly default-initialized will just work when inherited from. Second, if the base class has no default constructor, a derived class that stays silent about its base will not compile, because there is nothing for stage 2 to call.

You also cannot reach around the base and initialize its members yourself. Listing an inherited member such as m_serial in Keyboard's member initializer list is a compile error, because m_serial is not Keyboard's member to initialize. The base class owns that job. The next lesson covers the syntax for passing values to a specific base class constructor, which is how you fill in a base subobject with something other than its defaults.

Classes with No Base at All

For comparison, instantiating a class that inherits from nothing is the simple case that stages 1 through 4 collapse into. C++ allocates memory for the object and calls its constructor, which initializes the members and runs the body. There is no earlier layer to build, so there is nothing extra to sequence. Everything in this lesson is that same process applied once per level of inheritance.

Deeper Chains Apply the Rule Recursively

Nothing about the rule is limited to two levels. A class derived from a class that is itself derived from another class simply repeats stage 2 at each level: before any class can construct itself, its base must be finished, and that base has the same obligation to its base. The chain unwinds all the way to the top of the tree and then builds back down.

#include <iostream>

class Instrument
{
public:
    Instrument() { std::cout << "level 1: Instrument\n"; }
};

class Keyboard : public Instrument
{
public:
    Keyboard() { std::cout << "level 2: Keyboard\n"; }
};

class Piano : public Keyboard
{
public:
    Piano() { std::cout << "level 3: Piano\n"; }
};

class GrandPiano : public Piano
{
public:
    GrandPiano() { std::cout << "level 4: GrandPiano\n"; }
};

int main()
{
    GrandPiano hall {};

    return 0;
}
level 1: Instrument
level 2: Keyboard
level 3: Piano
level 4: GrandPiano

Creating one GrandPiano ran four constructors, in top-down order. The type you name decides how far down the chain the sequence goes, and the sequence is always a prefix of the same list:

Object you create Constructors that run, in order
Instrument Instrument
Keyboard Instrument, Keyboard
Piano Instrument, Keyboard, Piano
GrandPiano Instrument, Keyboard, Piano, GrandPiano

Each constructor completes fully before the next one begins, so at every point in the sequence the part of the object that already exists is a valid, fully initialized object of some class along the chain.

Teardown Runs the Sequence Backwards

Destruction mirrors construction exactly. The most-derived destructor body runs first, then its members are destroyed, and the base subobject is destroyed last, which is the only order that keeps the base alive for as long as anything derived might still use it.

#include <iostream>

class Instrument
{
public:
    Instrument() { std::cout << "Instrument built\n"; }
    ~Instrument() { std::cout << "Instrument released\n"; }
};

class Keyboard : public Instrument
{
public:
    Keyboard() { std::cout << "Keyboard built\n"; }
    ~Keyboard() { std::cout << "Keyboard released\n"; }
};

int main()
{
    {
        Keyboard upright {};
        std::cout << "upright is in use\n";
    }

    std::cout << "upright is gone\n";

    return 0;
}
Instrument built
Keyboard built
upright is in use
Keyboard released
Instrument released
upright is gone

Read the four construction and destruction lines together and the symmetry is clear: Instrument, Keyboard, then Keyboard, Instrument. Whatever was built first is torn down last.

Best Practice
Let each class initialize only its own members, and let the base class initialize the base subobject. Constructors that stay inside their own layer compose correctly at any depth of inheritance without you having to reason about the whole chain.

Summary

A derived object contains a base subobject: Inheritance embeds a complete base class object inside the derived one rather than copying the base's fields. Picture the object as a base part plus a derived part, which is why sizeof a derived class includes the base class's members.

Construction runs from most-base to most-derived: When a derived object is instantiated, the class at the top of the inheritance tree is constructed first and the most-derived class is constructed last. Creating one object of a derived type therefore runs one constructor per level of the hierarchy.

Four stages per level: Memory is allocated for the whole object, the base subobject is constructed, the class's own members are initialized in declaration order, and the constructor body runs last.

The default base constructor is the default choice: If a derived class does not say which base constructor to use, C++ calls the base class's default constructor. A derived class cannot initialize inherited members directly in its own member initializer list.

Non-derived classes are the simple case: A class with no base is allocated and then handed to its own constructor, with no earlier layer to build first.

Chains recurse: For Instrument to Keyboard to Piano to GrandPiano, creating a GrandPiano calls those four constructors in exactly that order, each finishing before the next begins.

Destruction is the mirror image: The most-derived destructor runs first and the base subobject is destroyed last, keeping every base layer alive for as long as the derived layers above it exist.

The ordering exists for one reason: a derived class commonly uses its base class's members and functions, while the base class knows nothing about what derives from it. Building parents before children is what makes that dependency safe.