Subclass Constructor Initialization When a derived class object is created, its constructor is responsible for initializing all members, including those inherited from the base class. This initialization can be performed in two primary ways:
Implicit Call: If the base class has a default constructor (or a constructor with default arguments), the derived class constructor will automatically call it. Explicit Call: For any base class constructor, including those with parameters, the derived class must explicitly call it within its own constructor's initializer list.
Consider the following example. The Base class has two constructors, one default and one parameterized. The Derived class demonstrates both implicit and explicit calls to the base class constructors.
#include <iostream>
#include <string>
class Base {
public:
Base() {
std::cout << "Base class default constructor" << std::endl;
}
Base(const std::string& name) {
std::cout << "Base class constructor with name: " << name << std::endl;
}
};
class Derived : public Base {
public:
// Implicitly calls Base's default constructor
Derived() {
std::cout << "Derived class constructor" << std::endl;
}
// Explicitly calls Base's parameterized constructor
Derived(const std::string& name) : Base(name) {
std::cout << "Derived class constructor with name: " << name << std::endl;
}
};
int main() {
std::cout << "Creating Derived object with default constructor:" << std::endl;
Derived d1; // Output: Base class default constructor, then Derived class constructor
std::cout << "
Creating Derived object with parameterized constructor:" << std::endl;
Derived d2("Example"); // Output: Base class constructor with name: Example, then Derived class constructor with name: Example
return 0;
}
Construction and Destruction Order The construction of a derived class object follows a strict sequence to ensure proper initialization of its entire object hierarchy. The order is:
Base Class Constructor: The constructor of the immediate base class is called first. Member Object Constructors: The constructors for any member objects (in the order they are declared in the class) are called next. Derived Class Constructor: Finally, the constructor body of the derived class itself is executed.
This sequence is often remembered as "parents first, then members, then self." The destruction process, handled by destructors, occurs in the exact reverse order. Let's examine a more complex example to illustrate this. The System class inherits from Module and contains two Component member objects. The output clearly demonstrates the construction and destruction sequence.
#include <iostream>
#include <string>
class Component {
std::string mName;
public:
Component(const std::string& name) : mName(name) {
std::cout << "Component constructor: " << mName << std::endl;
}
~Component() {
std::cout << "Component destructor: " << mName << std::endl;
}
};
class Module : public Component {
std::string mName;
public:
Module(const std::string& name) : Component(name), mName(name) {
std::cout << "Module constructor: " << mName << std::endl;
}
~Module() {
std::cout << "Module destructor: " << mName << std::endl;
}
};
class System : public Module {
Component mComp1;
Component mComp2;
std::string mName;
public:
System(const std::string& name) : Module(name), mComp1(name + "_1"), mComp2(name + "_2"), mName(name) {
std::cout << "System constructor: " << mName << std::endl;
}
~System() {
std::cout << "System destructor: " << mName << std::endl;
}
};
int main() {
System sys("Sys"); // Construction order: Component, Module, Component, Component, System
std::cout << std::endl;
return 0; // Destruction order: System, Component, Component, Module, Component
}
Running this code produces the following output, confirming the order:
Component constructor: Sys
Module constructor: Sys
Component constructor: Sys_1
Component constructor: Sys_2
System constructor: Sys
System destructor: Sys
Component destructor: Sys_2
Component destructor: Sys_1
Module destructor: Sys
Component destructor: Sys