Order of Calling Constructors/Destructors in Inheritance

Order of calling constructors/destructors in inheritance

  • Construction always starts with the base class. If there are multiple base classes then, construction starts with the left most base. (side note: If there is a virtual inheritance then it's given higher preference).
  • Then the member fields are constructed. They are initialized in the
    order they are declared
  • Finally, the class itself is constructed
  • The order of the destructor is exactly the reverse

Irrespective of the initializer list, the call order will be like this:

  1. Base class A's constructor
  2. class B's field named a (of type class A) will be constructed
  3. Derived class B's constructor

What is the order in which the destructors and the constructors are called in C++

The order is:

  1. Base constructor
  2. Derived constructor
  3. Derived destructor
  4. Base destructor

Example:

class B
{
public:
B()
{
cout<<"Construct B"<<endl;
}

virtual ~B()
{
cout<<"Destruct B"<<endl;
}
};

class D : public B
{
public:
D()
{
cout<<"Construct D"<<endl;
}

virtual ~D()
{
cout<<"Destruct D"<<endl;
}
};



int main(int argc, char **argv)
{
D d;
return 0;
}

Output of example:

Construct B

Construct D

Destruct D

Destruct B

Multiple levels of inheritance works like a stack:

If you consider pushing an item onto the stack as construction, and taking it off as destruction, then you can look at multiple levels of inheritance like a stack.

This works for any number of levels.

Example D2 derives from D derives from B.

Push B on the stack, push D on the stack, push D2 on the stack. So the construction order is B, D, D2. Then to find out destruction order start popping. D2, D, B

More complicated examples:

For more complicated examples, please see the link provided by @JaredPar

Change the order of constructors in inheritance

Your constant B::CONSTANT_B can be static, since it does not depend on a constructor argument.

statics are initialised before your class objects are constructed (unless those are static too!).

struct B : A
{
static const int CONSTANT_B = 3;

B() : A(CONSTANT_B)
{
write();
}
};

If B::CONSTANT_B itself took its value from a constructor argument, you'd probably have to name that argument twice in the ctor-member-initialiser. There are no trivial workarounds for that as far as I can imagine.

struct B : A
{
const int CONSTANT_B;

B(const int constant)
: A(constant)
, CONSTANT_B(constant)
{
write();
}
};

C++ Constructor/Destructor inheritance

Terminology, terminology...

OK, what do we mean by "Foo is inherited"? We mean that if objects of class A have Foo in its interface, then objects of class B which is a subclass of A also have Foo in its interface.

  • Constructors aren't a part of objects' interface. They belong directly to classes. Classes A and B may provide completely different sets of constructors. No "being inherited" here.

    (Implementation detail: each B's constructors calls some A's constructor.)

  • Destructors indeed are a part of each object's interface, since the object's user is responsible for calling them (i.e. directly with delete or indirectly by letting an object out of scope). Each object has exactly one destructor: its own destructor, which might optionally be a virtual one. It is always its own, and it's not inherited.

    (Implementation detail: B's destructor calls A's destructor.)

So: there's a connection between base and derived constructors and destructors, but it's not like "they're inherited".

I hope this answers what you have in mind.

In what order will base classes be destroyed?

There are rules (C++11 §12.4):

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).

The construction order is (§12.6.2/10):

In a non-delegating constructor, initialization proceeds in the following order:

— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.

— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

— Finally, the compound-statement of the constructor body is executed.

[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. — end note ]

So in simple cases, base constructors are called in the order in which the classes are listed in the declaration, and destructors run in reverse of that order.

Call of the destructors in multilevel inheritance (c++)

Inheritance is a red herring here. It's not relevant.

y and z have automatic storage duration and are required, in this case, to stay in scope until the closing brace of the function.

And z will be destructed before y. (Automatic variables go out of scope in the reverse order in which they were created, all other things being equal.)

Destructor ordering in inheritance hierarchy

Destructors execute in reverse order of constructors. That is pretty much all you need to know.

UPDATE: It holds even for virtual bases. You just have to realize that virtual bases are constructed before any other base class.



Related Topics



Leave a reply



Submit