If you inherit class 1 from class 2, then their destructors are called in what order?

Order of calling constructors during inheritance. Inheritance restrictions. Properties of a pointer (reference) to the base class

This topic is a continuation of the topic:

  • Inheritance. General concepts. Using private, protected, public modifiers when inheriting

Contents

  • 1. Calling class constructors during inheritance
  • 2. An example demonstrating the order in which constructors are called. 3 classes under consideration
  • 3. Passing arguments to the base class when calling constructors
  • 4. Example demonstrating passing arguments to the base class constructor
  • 5. Elements of a class that cannot be inherited
  • 6. Features of using a pointer to the base class
  • 7. An example demonstrating the use of a pointer to a base class
  • Related topics

Search other resources:

1. Calling class constructors during inheritance

If two classes form an inheritance hierarchy, then when an instance of a derived class is created, the constructor of the base class is first called, which constructs the object of the derived class. Then this constructor becomes unavailable and is extended with the code of the derived class constructor. Thus, the data of the base class is initialized first, then the data of the derived class is initialized.

If classes form a hierarchy, the destructors of those classes are called in reverse order of the constructors being called. The destructor of the derived class is called first, then the destructor of the base class is called.

Figure 1 shows the order of calling constructors for two classes A, B forming an inheritance hierarchy for the case of creating an instance of a derived class B.

If you inherit class 1 from class 2, then their destructors are called in what order?

Figure 1. The order of calling constructors for the case of two classes: 1 – class A constructor; 2 – class B constructor; 3 – class B destructor; 4 – class Adestructor

 

2. An example demonstrating the order in which constructors are called. 3 classes under consideration

The example declares 3 classes A, B, C, which form an inheritance hierarchy. Each class contains one constructor and one destructor. For the purpose of visualization, the code of constructors and destructors contains the output of the relevant information.

#include <iostream>
using namespace std;

// Base class
class A
{
public:
  // Constructor of class A
  A()
  {
    cout << "Constructor A::A()" << endl;
  }

  // Destructor of class A
  ~A()
  {
    cout << "Destructor A::~A()" << endl;
  }
};

// Derived classes
class B : public A
{
public:
  // Constructor
  B()
  {
    cout << "Constructor B::B()" << endl;
  }

  // Destructor
  ~B()
  {
    cout << "Destructor B::~B()" << endl;
  }
};

class C :public B
{
public:
  // Constructor
  C()
  {
    cout << "Constructor C::C()" << endl;
  }

  // Destructor
  ~C()
  {
    cout << "Destructor C::~C()" << endl;
  }
};

void main()
{
  // Create an instance of class C
  C obj; // A() => B() => C()
} // ~C() => ~B() => ~A()

Program result

Constructor A::A()
Constructor B::B()
Constructor C::C()
Destructor C::~C()
Destructor B::~B()
Destructor A::~A()

Based on the result obtained, the following conclusions can be drawn:

  • constructors are called in order from the base class A to the inherited class C, which is at the lowest level of the hierarchy;
  • destructors are called in the reverse order of calling constructors.

 

3. Passing arguments to the base class when calling constructors

If the base class has a constructor that takes parameters, then when creating an instance of a derived class, you must pass the appropriate arguments to the base class constructor. That is, you need to initialize the data of the base class in the constructor of the derived class.

Such initialization is carried out using a special syntax that looks like this:

// Base class
class Base
{
  // Base class constructor receiving parameters
  Base(params_Base)
  {
    // ...
  }
}

// Derived class
class Derived : Base
{
  // Derived class constructor - calls the base class constructor
  Derived(params_Derived) : Base(args_Base)
  {
    // ...
  }
}

here

  • Base, Derived – base and derived classes, respectively;
  • params_Base – parameters that the base class constructor receives;
  • arg_Base – arguments passed to the base class constructor;
  • params_Derived – parameters received by the derived class constructor.

If there is no constructor at all in the Base class, or there is only one parameterless constructor Base() (the default constructor), then there is no need to access the constructor of the Base class from the constructor of the derived class Derived.

  ⇑

4. Example demonstrating passing arguments to the base class constructor

The example declares two classes:

  • Point is the base class containing one parameterized constructor. The constructor receives 2 parameters;
  • PointColor is a class inherited from the Point class and extending the Point class with the property color (point color). The constructor of the PointColor class calls the constructor of the base class Point using special C++ syntax.
#include <iostream>
using namespace std;

// A class that describes a point
class Point
{
private:
  double x, y; // point coordinates

public:
  // Constructor that receives 2 parameters
  Point(double _x, double _y) : x(_x), y(_y)
  { }

  // Access methods
  double X() { return x; }
  double Y() { return y; }
};

// A class that inherits from the Point class, this class adds color to the Point class
class PointColor : public Point
{
private:
  int color; // additional field - color

public:
  // Constructor that takes 3 parameters,
  // this constructor calls the base class constructor Point(_x, _y)
  PointColor(double _x, double _y, int _color) : Point(_x, _y)
  {
    color = _color;
  }

  // Access method
  int Color() { return color; }
};

void main()
{
  // Create an instance of the PointColor class.
  // Constructors are called: Point(5, 8) => PointColor(2)
  PointColor pc(5, 8, 2);

  cout << "pc.x = " << pc.X() << endl;
  cout << "pc.y = " << pc.Y() << endl;
  cout << "pc.color = " << pc.Color() << endl;
}

In the above code, in the PointColor class, the constructor of this class calls the constructor of the base class Point, passing it two arguments (x, y coordinates).

// Constructor that takes 3 parameters,
// this constructor will call the base class constructor Point(_x, _y)
PointColor(double _x, double _y, int _color) : Point(_x, _y)
{
  color = _color;
}

The third parameter _color initializes the internal variable color.

After running the program will give the following result

pc.x = 5
pc.y = 8
pc.color = 2

 

5. Elements of a class that cannot be inherited

In C++, not all members of a class can be inherited because they are incompatible with the very idea of inheritance. These elements include:

  • constructors (all types of constructors);
  • destructor;
  • overloaded operators new;
  • overloaded assignment operators (=);
  • friend functions or friend relations. This means that if the base class has friend functions, then those functions are not friend in the inherited class.

 

6. Features of using a pointer to the base class

If classes form an inheritance hierarchy, then the following rule is true for these classes:

  • a pointer (reference) to a base class can point to an instance of that class and an instance of any derived class in the inheritance hierarchy. Or in other words, a pointer (reference) to a base class can be cast to the type of any derived class in the inheritance hierarchy.
  • thanks to this rule, the implementation of the polymorphism mechanism is ensured. You can read more about polymorphism here.

Figure 2 shows an example of a hierarchy and possible assignments to a pointer of values of the addresses of instances of derived classes

If you inherit class 1 from class 2, then their destructors are called in what order?

Figure 2. Pointer p to base class A can point to instances of derived classes inherited from base class A

 

7. An example demonstrating the use of a pointer to a base class

The example declares two classes Base and Derived. Classes form an inheritance hierarchy. The Derived class inherits from the Base class.

// Base class
class Base
{
  // ...
};

// Derived (inherited) class here the public keyword is required
class Derived : public Base
{
  // ...
};

void main()
{
  // 1. Declare a pointer to a base class
  Base* p1;

  // 2. Declare instances of base and derived class
  Base obj1;
  Derived obj2;

  // 3. Assign instance addresses to pointer
  p1 = &obj1; // It's possible
  p1 = &obj2; // It's possible, now p points to an instance of the derived class

  // 4. You can't do that
  Derived* p2; // Pointer to derived class
  p2 = &obj2; // so it is possible, the types are the same: Derived* <= Derived*
  p2 = &obj1; // compile error, base class cannot be extended
              // to derived class capabilities Derived* <= Base*
}

In the above example, the main() function declares a pointer to the base class Base and two instances (objects) of the Base and Derived classes, named obj1 and obj2, respectively. Then the pointer p is assigned in turn the values of the addresses of the instances obj1 and obj2. Assignment is successful.

The next step is to declare a pointer p2 to the derived class Derived for demonstration purposes. This pointer alternately takes the value of the addresses of the obj2 and obj1 instances. In the case of the obj2 instance, the assignment is correct

Derived* p2;
p2 = &obj2; // everything works here, types are the same

In case of assigning the address of the obj1 instance

p2 = &obj1;

the compiler throws an error. This is logical because the Base class instance obj1 cannot be extended to the capabilities of a Derived derived class because it does not inherit that class (the Base class does not inherit the Derived class).

 


  • Inheritance. General concepts. Using private, protected, public modifiers when inheriting
  • Polymorphism. Virtual functions. General concepts. Specifiers virtual, override. Examples
  • Abstract class. Pure virtual function. Examples

 


What order are destructors called?

Destructors for virtual base classes are called in the reverse order of declaration.

Which destructor is called first in inheritance?

This is why the constructor of base class is called first to initialize all the inherited members.

In what order destructors are executed in the inheritance hierarchy?

The destructors for these virtual base classes are executed in the reverse order they appear in a depth-first left-to-right traversal of the graph of base classes, where left to right refer to the order of appearance of base class names.

In what order are class constructors and class destructors called when a derived class object is created and deleted?

Destructors are called in reversed order of called constructors.

How destructors are called in inheritance?

Destructors are called automatically when a variable goes out of scope. Because the base class destructor is inherited, and because the derived class object "is" a base class object, both the derived class destructor (even if it is the "default" destructor) and the base class destructor are called automatically.