Category: C++ Constructors

https://zain.sweetdishy.com/wp-content/uploads/2026/02/Constructors.png

  • Virtual Destructor in C++

    virtual destructor is a destructor declared within the base class with the virtual keyword. When deleting a derived class object using a pointer to a base class, the base class should be defined with a virtual destructor.

    Virtual destructors help prevent the problem of memory leaks and undefined behavior. If a virtual destructor is not used, then only the base class destructor is called, and the resources of derived class is not cleaned up.

    The Syntax for declaring a virtual destructor is given below −

    classBase{public:virtual~Base(){// base class destructor}};

    Example

    The following example demonstrates how to use a virtual destructor. The virtual destructor calls the destructor of both classes i.e. base and child class −

    #include <iostream>usingnamespace std;classBase{public:Base(){
    		cout <<"Base Constructor\n";}virtual~Base(){
    		cout <<"Base Destructor\n";}};classDerived:public Base{public:Derived(){
    		cout <<"Derived Constructor\n";}~Derived(){
    		cout <<"Derived Destructor\n";}};intmain(){
    	Base *basePtr =newDerived();delete basePtr;return0;}

    The output of the above code is given below −

    Base Constructor
    Derived Constructor
    Derived Destructor
    Base Destructor
    

    Why We Need Virtual Destructors?

    Given below are the reasons why virtual destructors are needed −

    • When you do not use a virtual base class destructor while deleting a derived class object, it results in undefined behavior.
    • Virtual destructors make sure to delete the object of derived class too while deleting the base class object.
    • It avoids memory leak.
    • Virtual destructors maintain the order of execution of destructors i.e., first derived class, then base class.

    Example: Non-Virtual Destructor

    In the following example, the virtual destructor is not used. In the output, it can be observed that only the base class destructor has been called and the destructor of derived class is skipped.

    #include <iostream>usingnamespace std;classBase{public:// Non-virtual destructor~Base(){
    		cout <<"Base class destructor called.\n";}};classDerived:public Base{public:~Derived(){
    		cout <<"Derived class destructor also called.\n";}};intmain(){
    	Base* ptr =newDerived();// Only Base destructor will be calleddelete ptr;return0;}

    The output of the above code is given below −

    Base class destructor called.
    

    Example: Virtual Destructor

    In this example, we have used a virtual destructor on base class Base. In the output, it can be observed that the destructor of both base and derived class is called and it maintains the reverse order of deletion.

    #include <iostream>usingnamespace std;classBase{public:// Virtual destructorvirtual~Base(){
    		cout <<"Base class destructor called.\n";}};classDerived:public Base{public:~Derived(){
    		cout <<"Derived class destructor also called.\n";}};intmain(){
    	Base* ptr =newDerived();// Both Base class and derived class destructor will be calleddelete ptr;return0;}

    The output of the above code is given below −

    Derived class destructor also called.
    Base class destructor called.
    

    When to Use Virtual Destructors?

    You can use a virtual destructor in the following scenarios.

    • If a virtual function is used, then use virtual destructor. Since, virtual functions are used in polymorphism to override base class. Using a virtual destructor can free up memory of both, base and derived class.
    • In inheritance, make the destructor of base class a virtual destructor as the destructor of derived class is skipped and only the base class destructor is called, it may cause a memory leak.
    • If abstract base or pure virtual function is used, then use virtual destructor on base class.

    Virtual Destructor Table (Vtable)

    In C++, virtual table(vtable) is a lookup table which is used by the compiler to implement virtual functions or virtual destructors. For each class that has at least one virtual function or virtual destructor, the compiler will create a vtable for that class.

    vtable has pointers to all virtual functions and the virtual destructor of a class. In a class, each object has a hidden pointer known as vptr or virtual pointer. This vptr points to the vtable of the class, which is then used to call the respective destructor. Here is a diagram representation of the vtable for the given code −

    Virtual Destructor Table

    Example

    In this example, we have implemented the above code snippet to override the virtual functions of class A in class B and class C.

    #include <iostream>usingnamespace std;classA{public:virtualvoidf1(){
    		cout <<"A::f1 called"<< endl;}virtualvoidf2(){
    		cout <<"A::f2 called"<< endl;}virtual~A(){
    		cout <<"Class A destructor called"<< endl;}};classB:public A{public:voidf1()override{
    		cout <<"B::f1 called"<< endl;}voidf2()override{
    		cout <<"B::f2 called"<< endl;}~B()override{
    		cout <<"Class B destructor called"<< endl;}};classC:public A{public:voidf1()override{
    		cout <<"C::f1 called"<< endl;}voidf2()override{
    		cout <<"C::f2 called"<< endl;}~C()override{
    		cout <<"Class C destructor called"<< endl;}};intmain(){
    	A* ptrB =newB();
    	A* ptrC =newC();
    
    	cout <<"Calling functions using pointer B:"<< endl;
    	ptrB->f1();
    	ptrB->f2();
    
    	cout <<"Calling functions using pointer C:"<< endl;
    	ptrC->f1();
    	ptrC->f2();// Calling B's destructor then A's destructordelete ptrB;// Calling C's destructor then A's destructordelete ptrC;return0;}

    The output of the above code is given below −

    Calling functions using pointer B:
    B::f1 called
    B::f2 called
    Calling functions using pointer C:
    C::f1 called
    C::f2 called
    Class B destructor called
    Class A destructor called
    Class C destructor called
    Class A destructor called
    

    Conclusion

    The virtual destructor is used when working with inheritance and polymorphism. Its main purpose is to make sure that the destructors of derived classes are also called when an object is deleted through a base class pointer. This prevents memory leaks and undefined behavior.

  • Destructors in C++

    destructor is a special member function of a class that is executed automatically whenever an object of its class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class.

    Note: In C++, the static keyword has a different meaning. In this chapter, we’re using static memory allocation for stack-based / non-dynamic memory allocation.

    The syntax of defining a destructor manually is given below −

    ~class_name(){// body }

    Here’s the syntax to define a destructor outside the class, but first we need to declare the destructor in the class −

    class_name {public:// Destructor Declaration~class_name();}// Defining Destructorclass_name::~class_name(){// Body}

    Defining a Destructor Inside a Class

    In this example, we have used the above syntax for defining a destructor manually inside a class. Here, destructor is not needed, we have used destructor just to illustrate how a destructor is defined inside a class −

    #include <iostream>usingnamespace std;classExample{public:// Constructor calledExample(void){
             cout <<"Constructor is called"<< endl;}// Defining destructor inside class~Example(void){
             cout <<"Destructor is called"<< endl;}};intmain(){
       Example ex;return0;}

    The output of the above code is given below −

    Constructor is called
    Destructor is called
    

    Defining a Destructor Outside a Class

    The example below demonstrates how to define a destructor(Example) outside the class using scope resolution operator. But first, it needs to be declared inside the class.

    #include <iostream>usingnamespace std;classExample{public:// Constructor calledExample(void){
             cout <<"Constructor is called"<< endl;}// Declaring destructor inside class~Example();};// Defining destructor outside class using scope resolution operatorExample::~Example(void){
       cout <<"Destructor is called"<< endl;}intmain(){
       Example ex;return0;}

    The output of the above code is given below −

    Constructor is called
    Destructor is called
    

    Why Do We Need Custom Destructors?

    C++ provides a default destructor for every class as the classes are created. The default destructor cleans up the statically allocated memory. But, if we have used a pointer for dynamic memory allocation using new, then we need to define a custom destructor with delete operator to clean up the memory.

    In this example, the destructor Example1 is just used for displaying the message and not to free the memory as the memory of class Example1 gets freed automatically. But the destructor Example2 is used for freeing the memory using delete operator.

    #include <iostream>usingnamespace std;classExample1{public:// Constructor calledExample1(){
             cout <<"Constructor of Example1 is called"<< endl;}// Destructor called~Example1(){
             cout <<"Destructor of Example1 is called"<< endl;}};classExample2{private:int*ptr;public:Example2(){
             ptr =newint;// dynamically allocated memory*ptr =42;
             cout <<"Constructor of Example2 is called with ptr Value = "<<*ptr << endl;}// Destructor called to free dynamically allocated memory~Example2(){delete ptr;// dynamically allocated memory is freed
             cout <<"Destructor of Example2 is called"<< endl;}};intmain(){
       Example1 ex1;// object with static memory allocation
       Example2 ex2;// object with dynamic memory allocationreturn0;}

    The output of the above code is given below −

    Constructor of Example1 is called
    Constructor of Example2 is called with ptr Value = 42
    Destructor of Example2 is called
    Destructor of Example1 is called
    

    Properties of Destructors in C++

    Destructors in C++ have the following properties −

    • Destructors are automatically called when an object goes out of scope.
    • Destructor has the same name as the class and is denoted using tilde(~) sign.
    • It is automatically created when a class is created.
    • Destructors do not have any return type and do not accept any parameters/arguments.
    • You can not define more than one destructor.
    • Destructors cannot be inherited.
    • Destructors cannot be overloaded.

    Automatic Destructor Call for Statically Allocated Objects

    For objects that are created using static memory allocation, destructors are automatically called. Below is an example −

    #include <iostream>usingnamespace std;classMyClass{public:MyClass(){
             cout <<"Constructor called"<< endl;}~MyClass(){
             cout <<"Destructor called automatically"<< endl;}};intmain(){
       cout <<"Creating an object using static memory allocation"<< endl;{
          MyClass obj;
          cout <<"Object created"<< endl;}// Object goes out of scope here,//destructor called automatically
       cout <<"Object destroyed"<< endl;return0;}

    The output of the above code is given below −

    Creating an object using static memory allocation
    Constructor called
    Object created
    Destructor called automatically
    Object destroyed
    

    C++ Destructor for Dynamic Objects

    For objects that are created using dynamic memory allocation, you need to manually call the destructor using delete. In the example below, we have manually deleted the object using the delete operator:

    #include <iostream>usingnamespace std;classMyClass{public:MyClass(){
              cout <<"Constructor called"<< endl;}~MyClass(){
             cout <<"Destructor called"<< endl;}};intmain(){
       cout <<"Creating an object using dynamic memory allocation:"<< endl;// Dynamically creating an object
       MyClass *obj =newMyClass();
    
       cout <<"Object created"<< endl;// Manually invoking destructordelete obj;
       cout <<"Object destroyed manually using delete"<< endl;return0;}

    The output of the above code is given below −

    Creating an object using dynamic memory allocation:
    Constructor called
    Object created
    Destructor called
    Object destroyed manually using delete
    

    Destructor Call Order for Multiple Objects

    Destructors are called in reverse order of construction for multiple objects. In the example below, we can see that the destructors are called in the reverse order −

    #include <iostream>usingnamespace std;classMyClass{private:int id;public:MyClass(int num):id(num){
             cout <<"Constructor called for object "<< id << endl;}~MyClass(){
              cout <<"Destructor called for object "<< id << endl;}};intmain(){
    	cout <<"Creating 3 objects:"<< endl;{
    		MyClass obj1(1);// First object
    		MyClass obj2(2);// Second object
    		MyClass obj3(3);// Third object
    		cout <<"All objects created"<< endl;}// All objects go out of scope here
    
    	cout <<"All objects destroyed"<< endl;return0;}

    The output of the above code is given below −

    Creating 3 objects:
    Constructor called for object 1
    Constructor called for object 2
    Constructor called for object 3
    All objects created
    Destructor called for object 3
    Destructor called for object 2
    Destructor called for object 1
    All objects destroyed
    

    Destructors with Arrays

    To clean the memory after an array gets deleted or gets out of scope, we need to call destructor for each array item to avoid any memory leak. There can be three different types of scenarios while using a destructor with an array.

    • Using Destructor with Static Array
    • Using Destructor with a Dynamic Array
    • Using Destructor with an Array of Pointers to Objects

    Using a Destructor with a Static Array

    In this example, we have a static array of objects, and the memory is freed automatically by the compiler. Here, the destructor is used just for displaying the message.

    #include <iostream>usingnamespace std;classExample{private:int id;public:Example(int i):id(i){
             cout <<"Constructor called for object "<< id << endl;}~Example(){
             cout <<"Destructor called for object "<< id << endl;}};intmain(){
       cout <<"Creating array of 3 objects:"<< endl;
       Example arr[3]={Example(1),Example(2),Example(3)};
    
       cout <<"Array created"<< endl;return0;// Destructors called automatically}

    The output of the above code is given below −

    Creating array of 3 objects:
    Constructor called for object 1
    Constructor called for object 2
    Constructor called for object 3
    Array created
    Destructor called for object 3
    Destructor called for object 2
    Destructor called for object 1
    

    Using a Destructor with a Dynamic Array

    In this example, a dynamic array of objects is created using new[] operator. Here, the destructor is used with delete[] operator to clear the memory.

    #include <iostream>usingnamespace std;classStudent{private:int rollNo;public:Student(int r =0)// constructor with default argument{
             rollNo = r;
             cout <<"Constructor called for roll no: "<< rollNo << endl;}~Student(){
             cout <<"Destructor called for roll no: "<< rollNo << endl;}};intmain(){
       cout <<"Creating dynamic array of 3 students:"<< endl;
    
       Student *students =new Student[3]{101,102,103};// initialize with roll numbers
    
       cout <<"\nDeleting array:"<< endl;delete[] students;// destructor for all 3 objectsreturn0;}

    The output of the above code is given below −

    Creating dynamic array of 3 students:
    Constructor called for roll no: 101
    Constructor called for roll no: 102
    Constructor called for roll no: 103
    
    Deleting array:
    Destructor called for roll no: 103
    Destructor called for roll no: 102
    Destructor called for roll no: 101
    

    Using a Destructor with an Array of Pointers to Objects

    In this example, an array of pointers to objects is created. Here, the destructor is used with the delete operator to free the memory of each object individually as each pointer is pointing to a uniquely allocated object.

    #include <iostream>usingnamespace std;classBook{private:
          string title;public:Book(string t):title(t){
             cout <<"Book created: "<< title << endl;}~Book(){
            cout <<"Book destroyed: "<< title << endl;}};intmain(){
       cout <<"Creating array of 3 books:"<< endl;
        Book *library[3];// Creating individual book objects
       library[0]=newBook("C++ Basics");
       library[1]=newBook("CSS Basics");
       library[2]=newBook("Javascript Basics");
    
       cout <<"\nDeleting books:"<< endl;// Deleting each object individuallyfor(int i =0; i <3; i++){delete library[i];}return0;}

    The output of the above code is given below −

    Creating array of 3 books:
    Book created: C++ Basics
    Book created: CSS Basics
    Book created: Javascript Basics
    
    Deleting books:
    Book destroyed: C++ Basics
    Book destroyed: CSS Basics
    Book destroyed: Javascript Basics
    

    Common Mistakes While Working with Destructors

    Some of the common beginner mistakes while working with destructors are listed below −

    • Using destructor for statically allocated memory. It gets deleted automatically, so there is no need to use a destructor.
    • For dynamically allocated memory, forgetting to use the delete.
    • In inheritance, not declaring the destructor as virtual in the base class.
    • For arrays, use delete[] instead of delete.
    • Trying to delete an already-deleted memory twice, also known as double deletion. Set the pointer to nullptr after deleting it, and check the pointer for nullptr before deletion.

    Conclusion

    Destructors are special member functions to clean up memory when objects go out of scope or program is executed. In C++, there is a default destructor for statically allocated memory, and custom destructors are used for clearing the dynamically allocated memory using the new operator.

  • Dynamic Initialization Using Constructors in C++

    Dynamic Initialization Using Constructors

    In C++, Dynamic initialization is the process of initializing variables or objects at runtime using constructors.

    Where constructors play an important role in object creation and can be used to initialize both static and dynamic data members of a class.

    While creating an object, its constructor is called and if the constructor contains logic to initialize the data members with values, is known as dynamic initialization. This is helpful because here the value is calculated, retrieved, or determined during runtime, which is more flexible than static initialization.

    Syntax

    Here is the following syntax for dynamic initialization using constructors.

    ClassName* objectName =newClassName(constructor_arguments);

    Here, ClassName is the class type.

    objectName is the pointer to the object.

    constructor_arguments are the arguments passed to the constructor.

    Example of Dynamic Initialization Using Constructors

    Here is the following example of dynamic initialization using constructors.

    #include <iostream>usingnamespace std;classRectangle{public:int width, height;// Constructor to initialize width and heightRectangle(int w,int h):width(w),height(h){}voiddisplay(){
          cout <<"Width: "<< width <<", Height: "<< height << endl;}};intmain(){// Dynamically creating a Rectangle object using the constructor
       Rectangle* rect =newRectangle(10,5);// Display the values
       rect->display();// Deallocate memorydelete rect;return0;}

    Output

    Width: 10, Height: 5
    

    Explanation

    • The new Rectangle(10, 5) dynamically created a Rectangle object having width 10 and height 5 using the constructor.
    • This rect->display() is displaying the rectangle’s dimensions.
    • The delete rect; deallocates the memory used by the Rectangle object.

    Why Use Constructors for Dynamic Initialization?

    • Allows initialization with values known only at runtime.
    • Simplifies object creation and initialization logic.
    • Combines initialization and validation in a single step.

    Using a constructor to initialize dynamically within C++ makes it so much easier to create an object where the values get determined only at runtime. Encapsulation of initialization logic within the constructor makes the code clean, efficient, and more maintainable; use it whenever object initialization depends upon runtime data.

  • C++ – Constructor Initialization List

    When instantiating objects, constructors often handle the initialization of member variables. For such members, an initialization list for constructors provides an abbreviated and efficient way of their initialization before the constructor’s body is executed. Apart from performance, sometimes it also compulsory because of const variables or members of a base class.

    What is a Constructor Initialization List?

    A constructor initialization list is a procedure to initialize member variables directly, hence, there is no default constructor that is copied and then assigned.

    Syntax

    The following syntax of initialization of constructor list is as follows−

    ClassName(type1 param1, type2 param2):member1(param1),member2(param2){// Constructor body}

    Here, member1 and member2 are initialized with param1 and param2 before the constructor body runs.

    Example of Constructor Initialization List

    Heres a simple example demonstrating how to use an initialization list.

    #include <iostream>#include <string>classStudent{public:Student(const std::string& name,int age):name(name),age(age){}voiddisplay()const{
          std::cout <<"Name: "<< name <<", Age: "<< age <<"\n";}private:
          std::string name;int age;};intmain(){
       Student s("Navya",20);
       s.display();return0;}

    Output

    Name: Navya, Age: 20
    

    Why Use Constructor Initialization Lists?

    • To avoid default initialization followed by reassignment, to save time and resources.
    • It mandatory for certain types of const variables, reference members, and base class members.
    • It keeps all initialization logic in one place, separate from the constructor body.

    Special Cases

    In the following, we will discuss few special cases for constructor initialization list −

    Const or Reference Members

    Const variables and reference members cannot be reassigned, so they must be initialized in an initialization list,

    classConfig{public:Config(const std::string& product,constint& model):product(product),model(model){}private:const std::string product;constint& model;};

    Base Class Initialization

    When a derived class inherits from a base class, you can use an initialization list to call the base class constructor,

    class Base { public: Base(int value) : baseValue(value) {} protected: int baseValue; }; class Derived : public Base { public: Derived(int value, int extra) : Base(value), extraValue(extra) {} private: int extraValue; };

  • C++ – Delegating Constructors

    C++ Delegating Constructors

    Delegating constructors is a feature that simplifies the way constructors in a class handle the initialization task. It makes it easier to maintain object initialization by reducing redundancy, and by allowing one constructor to call another in the same class.

    Use of Delegating Constructors

    In class design, multiple constructors are often used to handle different initialization scenarios. However, this can lead to repetitive code because each constructor may duplicate similar initialization logic.

    By using the delegating constructors, code redundancy can be avoided. A single “main” constructor can handle most initialization tasks, while other constructors delegate to it.

    This approach follows the DRY (Don’t Repeat Yourself) principle and makes the code easier to maintain.

    Syntax of Delegating Constructors

    The syntax for a delegating constructor involves calling another constructor in the initializer list.

    classExample{public:// Primary constructor	  Example(int value):data(value){}// Delegating constructorExample():Example(0){}private:int data;};

    Where,

    • The Example(int value) is the main constructor that does the real initialization.
    • Example() is a delegating constructor that calls Example(int value) with a default value of 0.

    Rules for Using Delegating Constructors

    The following rules are applied when using delegating constructors in C++11 and later:

    • A constructor can delegate to only one other constructor in C++11 and later.
    • Delegation must occur within the same class.
    • Circular delegation (like A() : A(x) and A(x) : A()) is prohibited and will result in a compile-time error.

    Example of Delegating Constructors

    Here is a basic simple program for delegating constructors:

    #include <string>#include <iostream>classStudent{public:// Primary constructorStudent(const std::string& name,int age,double grade):name(name),age(age),grade(grade){}// Delegating constructor with default gradeStudent(const std::string& name,int age):Student(name, age,0.0){}// Delegating constructor with default age and gradeStudent(const std::string& name):Student(name,18,0.0){}voiddisplay()const{
          std::cout <<"Name: "<< name 
          <<", Age: "<< age 
          <<", Grade: "<< grade <<"\n";}private:
          std::string name;int age;double grade;};intmain(){
       Student s1("Navya",20,90.5);
       Student s2("Divya",22);
       Student s3("Kavya");
    
       s1.display();
       s2.display();
       s3.display();return0;}

    Output

    Name: Navya, Age: 20, Grade: 90.5  
    Name: Divya, Age: 22, Grade: 0  
    Name: Kavya, Age: 18, Grade: 0
    

    Advantages of Delegating Constructors

    The following are the advantages of using delegating constructors:

    • Centralized Initialization − By consolidating initialization logic into a single constructor, your code becomes easier to read and maintain
    • Avoidance of Redundancy − Reusing constructor logic eliminates duplicated code.
    • Ease of Modification − Changes to initialization logic need to be made only in the primary constructor.
  • C++ – Constructor with Default Arguments

    A constructor is a special member function in a class, which is automatically called when an object is created. These are used to initialize the object with values or default settings.

    Whereas default arguments in C++ allow to specify default values for function or constructor parameters.

    Constructor with Default Arguments

    A constructor with default arguments is a constructor that allows for the creation of an object using optional parameters. Where the default values for the parameters are provided, so when the user doesn’t pass any values, the default value is used.

    Syntax

    Here is the syntax given for the constructor with default arguments:

    classClassName{public:ClassName(parameter_Type parameter_Name = default_Value,
                  parameter_Type2 parameter_Name2 = default_Value2);};
    • Here, the constructor has the same name as the class
    • Default values are provided for one or more parameters.
    • If no value is passed by the user, then this default value will be used.

    Example of Constructor with Default Arguments

    Here is the following example for constructor with default arguments:

    #include <iostream>usingnamespace std;// Function with a default argumentvoidprintMessage(string message ="Hello, Tutorialspoint Learner"){
       cout << message << endl;}intmain(){// Calling the function without an argumentprintMessage();// Prints the default message: "Hello, World!"// Calling the function with a custom argumentprintMessage("Hi, there!");// Prints the custom message: "Hi, there!"return0;}

    Output

    Hello, Tutorialspoint Learner
    Hi, there!
    

    Explanation

    • A function printMessage() is created, giving a parameter of the default value “Hello, Tutorialspoint Learner”.
    • Now in main(), printMessage() function is called without any argument, so the default argument “Hello, Tutorialspoint Learner” is used.
    • whereas in printMessage(“Hi, there!”), we explicitly passed the value “Hi, there!” so this will override the default argument.

    Constructor with Multiple Default Arguments

    A constructor with multiple default arguments gives the user access to specify default values for more than one parameter. This provides more flexibility and access to pass any combination of arguments.

    Example

    Here is the following example for constructor with multiple default arguments:

    #include <iostream>usingnamespace std;classBox{public:int length, width, height;// Constructor with multiple default argumentsBox(int l =5,int w =10,int h =2){// Default values for length,    width, and height
             length = l;
             width = w;
             height = h;}voiddisplay(){
             cout <<"Length: "<< length <<", Width: "<< width <<", Height: "<< height << endl;}};intmain(){// Creating objects with different numbers of arguments
       Box box1;             
       Box box2(15);  
       Box box3(15,20);     
       Box box4(15,20,25);// Displaying the objects' values
       box1.display();
       box2.display();
       box3.display();
       box4.display();return0;}

    Output

    Length: 5, Width: 10, Height: 2
    Length: 15, Width: 10, Height: 2
    Length: 15, Width: 20, Height: 2
    Length: 15, Width: 20, Height: 25
    

    Explanation

    • Firstly, the class box is defined with three public member variables: length and width, where the constructor Box(int l = 5, int w = 10, int h = 2) has default arguments for all three parameters.
    • In object Box box1; no argument is provided, so the default constructor is called with default values, resulting in “Length: 5, Width: 10, Height: 2”.
    • In Box box2(15); length is provided as 15, but width and height are not provided, So it uses the default values respectively.
    • In Box box3(15, 20); length and width are provided with values 15 and 20 respectively, so it will override the default values and result accordingly.

    Key Features of Constructors with Default Arguments

    While it is similar to regular functions, it provides more flexibility and convenience while creating objects.

    Here in the following, we will discuss its all key features.

    1. Default values for parameters and flexibility in object creation

    Here the constructor can have default values for one or more parameters, which can be used when no argument is provided by the caller and allows multiple ways to create an object.

    2. Avoiding multiple constructor overloads

    You might need to load the constructor for every combination of arguments, which will make the code bulkier, but with default arguments, the constructor can be written once and it will handle different cases automatically.

    3. Order of Default Arguments

    In the case of multiple default value parameters, you cannot skip default arguments in the middle once you start providing defaults from the right.

    Syntax

    Box(int l =1,int w);// Invalid: 'w' has no default, but 'l' does.

    4. Default Arguments Can Be Used with Const Members

    If your class has const members, then default arguments can be provided in the constructor to make initialization easier.

    Syntax

    classBox{public:constint length, width;Box(int l =5,int w =10):length(l),width(w){}};

    This constructor uses default arguments (length = 5 and width = 10) to initialize the const members.

  • C++ – Constructor Overloading

    Constructor Overloading

    In C++, constructor overloading is a concept in object-oriented programming (OOP), where the user can define multiple constructors with the same name in a class with each having a different parameter list.

    Syntax

    Here’s the syntax for constructor overloading in C++.

    classClassName{public:// Constructor with no parameters (default constructor)ClassName(){// Initialization code}// Constructor with one parameterClassName(type param1){// Initialization code using param1}// Constructor with two parametersClassName(type param1, type param2){// Initialization code using param1 and param2}// Constructor with more parameters if neededClassName(type param1, type param2, type param3){// Initialization code using param1, param2, and param3}};

    Example of Constructor Overloading

    In this example, we will see how Constructor overloading allows the “Rectangle class” to have multiple constructors, each with a different parameter list. when we create an object of the rectangle class, the compiler automatically chooses the constructor that perfectly fits based on the arguments passed, showing how constructor overloading provides flexibility.

    Here is the following example of constructor overloading in C++.

    #include <iostream>usingnamespace std;classRectangle{public:int length, width;// Default constructor (no parameters)Rectangle(){
             length =1;
             width =1;}// Constructor with one parameter (square)Rectangle(int side){
             length = side;
             width = side;}// Constructor with two parameters (rectangle)Rectangle(int l,int w){
             length = l;
             width = w;}// Method to display the area of the rectanglevoiddisplayArea(){
             cout <<"Area: "<< length * width << endl;}};intmain(){// Using different constructors
       Rectangle rect1;// Default constructor
       Rectangle rect2(5);// Constructor with one parameter
       Rectangle rect3(5,3);// Constructor with two parameters
    
       rect1.displayArea();
       rect2.displayArea();
       rect3.displayArea();return0;}

    Output

    Area: 1
    Area: 25
    Area: 15
    

    Explanation

    • Firstly, we defined a class rectangle, with two public member variables, length and width.
    • Then a default constructor Rectangle() with values length and width equal to 1, then Constructors with One Parameter Rectangle(int side) and Two Parameters Rectangle(int l, int w).
    • When no arguments passed Rectangle rect1; the default constructor is called initializing length and width to 1.
    • When one argument is passed, Rectangle rect2(5); the constructor with one parameter is called, initializing both length and width to 5.
    • when two arguments are passed Rectangle rect3(5, 3); the constructor with two parameters is called, initializing length to 5 and width to 3.

    Benefits of Constructor Overloading

    Constructor Overloading provides various benefits, making it an essential feature for creating flexible and efficient classes.

    1. Flexibility in Object Initialization

    It gives you multiple ways of initializing an object or Multiple Initialization Options.

    2. Cleaner and Readable Code with enhanced Code Maintainability

    By providing different ways of initializing an object, it reduces the need for multiple setter methods or complex initialization logic, avoids redundancy, and provides simpler object creation, which ultimately gives cleaner and more readable code and easier to modify.

    3. Encapsulation of Initialization Logic

    It also encapsulates the initialization logic within the constructor, which means the initialization logic is managed inside the constructor rather than being spread across various methods or outside the class.

    4. Simplifies Object Cloning (Copy Constructors)

    Constructor overloading allows to defined copy constructor to handle both shallow and deep copying objects, this makes sure that the object is easily copied.

  • C++ Copy Constructor

    Copy Constructor

    The copy constructor is a constructor that creates an object by initializing it with an object of the same class which has been created previously. The copy constructor is used to −

    • Initialize one object from another of the same type.
    • Copy an object to pass it as an argument to a function.
    • Copy an object to return it from a function.

    If a copy constructor is not defined in a class, the compiler itself defines one.If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.

    Syntax

    The most common form of copy constructor is shown here −

    classname(const classname &obj){// body of constructor}

    Here, obj is a reference to an object that is being used to initialize another object.

    Example of Copy Constructor

    The following example demonstrates the use of the copy constructor:

    #include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
       cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
       ptr =newint;*ptr = len;}Line::Line(const Line &obj){
       cout <<"Copy constructor allocating ptr."<< endl;
       ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
       cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
       cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
       Line line(10);display(line);return0;}

    When the above code is compiled and executed, it produces the following result −

    Normal constructor allocating ptr
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Freeing memory!
    

    Copy Constructor to Create New Object

    You can create a new object by using the existing object through the concept of a copy constructor.

    In the following example, the copy constructor is used to create a new object as a copy of an existing object.

    Example

    Let us see the same example but with a small change to create another object using existing object of the same type −

    #include <iostream>usingnamespace std;classLine{public:intgetLength(void);Line(int len );// simple constructorLine(const Line &obj);// copy constructor~Line();// destructorprivate:int*ptr;};// Member functions definitions including constructorLine::Line(int len){
       cout <<"Normal constructor allocating ptr"<< endl;// allocate memory for the pointer;
       ptr =newint;*ptr = len;}Line::Line(const Line &obj){
       cout <<"Copy constructor allocating ptr."<< endl;
       ptr =newint;*ptr =*obj.ptr;// copy the value}Line::~Line(void){
       cout <<"Freeing memory!"<< endl;delete ptr;}intLine::getLength(void){return*ptr;}voiddisplay(Line obj){
       cout <<"Length of line : "<< obj.getLength()<<endl;}// Main function for the programintmain(){
    
       Line line1(10);
    
       Line line2 = line1;// This also calls copy constructordisplay(line1);display(line2);return0;}

    When the above code is compiled and executed, it produces the following result −

    Normal constructor allocating ptr
    Copy constructor allocating ptr.
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Copy constructor allocating ptr.
    Length of line : 10
    Freeing memory!
    Freeing memory!
    Freeing memory!
    

    Implicit vs. Explicit Copy Constructors

    In C++, there are two types of Copy Constructors that’s Implicit and Explicit. Here we will discuss the difference between these two.

    Implicit Copy Constructor

    If the user doesn’t define their own copy constructor, then the compiler automatically provides an implicit copy constructor. It performs a shallow copy of the object, which means that it copies the values of each member of the object to the new object.

    When is the Implicit Copy Constructor called?

    • When a user passes an object by value to a function.
    • When the user returns an object by value from a function.
    • When the user initializes an object with another object of the same type (copy initialization).

    Explicit (User-Defined) Copy Constructor

    It is the user-defined constructor. This gives you access to customize the copy behavior like creating a deep copy instead of the default shallow copy.

    Example

    Here is the example for both explicit and implicit copy constructors in C++:

    #include <iostream>usingnamespace std;classMyClass{private:int value;public:// ConstructorMyClass(int v):value(v){}// Explicit Copy ConstructorMyClass(const MyClass& other):value(other.value){
        cout <<"Explicit Copy Constructor called"<< endl;}voiddisplay()const{ cout <<"Value: "<< value << endl;}};voidprocessValue(MyClass obj){// Implicit copy constructor will be called here
      obj.display();}intmain(){
      MyClass obj1(10);// Constructor called
      MyClass obj2 = obj1;// Explicit copy constructor called
      obj1.display();
      obj2.display();processValue(obj1);// Implicit copy constructor calledreturn0;}

    When the above code is compiled and executed, it produces the following result −

    Explicit Copy Constructor called
    Value: 10
    Value: 10
    Explicit Copy Constructor called
    Value: 10
    

    Rule of Three/Five

    The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:

    The Rule of Three and Rule of Five suggest while defining a copy constructor (ClassName(const ClassName& other)) you should also define:

    • Rule of Three:
      • destructor (~ClassName()).
      • And copy assignment operator (ClassName& operator=(const ClassName& other)), to ensure that memory is correctly managed.
    • Rule of Five:
      • move constructor (ClassName(ClassName&& other)).
      • move assignment operator (ClassName& operator=(ClassName&& other))”. 

    These special member functions are necessary for the proper management of dynamic memory and other and other resources like file handling or network connections in a class.

    Deep Copy vs. Shallow Copy

    In C++, deep copy and shallow copy are different ways of copying objects and they are important when a class involves dynamic memory management.

    1. Shallow Copy

    It occurs when an object is copied in such a way that both original and copied objects share the same resources. This means that the copy constructor or copy assignment operator simply copies the values of data members (like pointers), without allocating new memory or making independent copies of the resources.

    Example

    #include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// ConstructorMyClass(int value){
        data =newint(value);// Allocate memory}// Shallow Copy ConstructorMyClass(const MyClass& other){
        data = other.data;// Copy pointer only}// Destructor~MyClass(){delete data;// Free memory}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
      MyClass obj1(42);// Create an object
      MyClass obj2 = obj1;// Use shallow copy constructor
    
      obj1.showData();
      obj2.showData();return0;}

    When the above code is compiled and executed, it produces the following result −

    Data: 42
    Data: 42
    free(): double free detected in tcache 2
    

    2. Deep Copy

    It occurs when an object is copied by allocating new memory for its own copy of the resources, making sure that the original and copied object is completely independent. Avoids double-free errors or dangling pointers.

    Example

    #include <iostream>usingnamespace std;classMyClass{private:int* data;// Pointer to an integerpublic:// Constructor: Dynamically allocate memory // and initialize with valueMyClass(int value){ data =newint(value);}// Deep Copy Constructor// Allocates new memory and copies the valueMyClass(const MyClass& other){ data =newint(*other.data);}// Destructor to clean up memory~MyClass(){delete data;}// Display the valuevoidshowData()const{ cout <<"Data: "<<*data << endl;}};intmain(){
      MyClass obj1(42);// Create an object
      MyClass obj2 = obj1;// Use deep copy constructor
    
      obj1.showData();// Display data from obj1
      obj2.showData();// Display data from obj2return0;}

    When the above code is compiled and executed, it produces the following result −

    Data: 42
    Data: 42
  • C++ – Parameterized Constructors

    In C++, constructors are special member functions, which are called automatically, when an object is created. There are two main types of constructors: default constructors and parameterized constructors.

    A default constructor is a constructor that does not take any parameters or has default values for all parameters.

    whereas a parameterized constructor is a constructor, which takes one or more parameters and is used to initialize an object with specific values passed when an object is created.

    In this chapter, we will learn only about the Parameterized Constructor.

    C++ Parameterized Constructors

    C++ parameterized constructor is a constructor, which accepts one or more arguments or parameters, to initialize an object with specific values, when created. Unlike the default constructor, which takes no arguments, a parameterized constructor takes one or more arguments.

    Syntax

    Here is the following syntax for declaring a parameterized constructor:

    ClassName(parameters){// Initialization code}

    Example of Parameterized Constructor

    Here is the following example of a parameterized constructor in C++:

    #include <iostream>usingnamespace std;classMyClass{public:int a, b;// Parameterized constructor with two argumentsMyClass(int x,int y){
             a = x;// Initialize 'a' with the value of 'x'
             b = y;// Initialize 'b' with the value of 'y'
             cout <<"Parameterized constructor called"<< endl;}// Method to display values of 'a' and 'b'voiddisplay(){
             cout <<"a: "<< a <<", b: "<< b << endl;}};intmain(){
       MyClass obj1(10,20);// Calls the parameterized constructor with 10 and 20
       obj1.display();// Output: a: 10, b: 20return0;}

    Output

    Parameterized constructor called
    a: 10, b: 20
    

    Explanation

    • First defined the class named MyClass, with two public data members a and b of int type.
    • Then a parameterized constructor, MyClass(int x, int y), takes two arguments (int x, int y) and initializes them a and b with values passed when the object is created.
    • Now when the MyClass obj1(10, 20) is called, the parameterized constructor will be invoked.
    • and display() method will print the values of a and b.

    Multiple Parameterized Constructors (Constructor Overloading)

    Constructor overloading or multiple parameterized constructors in C++, is a concept, which allows users to define multiple constructors in the same class with different parameter lists, where each constructor can initialize the object differently depending on the arguments passed while creating an object.

    Key points

    • Same Constructor Name − All overloaded constructors must have the same name as the class.
    • Different Parameters − Constructors must have a different number or types of parameters.
    • Flexibility − Constructor overloading also gives flexibility during object initialization by allowing the same class to be instantiated in various ways.

    Syntax

    Here is the following syntax for multiple parameterised constructor:

    classClassName{public:// Default constructor (no parameters)ClassName(){// Initialization code}// Parameterized constructor with one parameterClassName(Type1 param1){// Initialization code using param1}// Parameterized constructor with two parametersClassName(Type1 param1, Type2 param2){// Initialization code using param1 and param2}// Parameterized constructor with three parametersClassName(Type1 param1, Type2 param2, Type3 param3){// Initialization code using param1, param2, and param3}};

    Parameterized Constructors with Default Arguments

    A parameterized constructor with default arguments is a constructor, which allows a user to provide default values for one or more parameters, which means you can either pass values while creating the object or let the constructor use the default values for the missing parameters.

    Syntax

    Here is the following syntax for a parameterized constructor with default arguments:

    classClassName{public:// Constructor with default argumentsClassName(type1 param1 = default_value1, type2 param2 = default_value2,...){// Constructor implementation}};

    Advantages of Using Parameterized Constructors

    Parameterized constructors offer various benefits, which make object initialization more flexible, clean, and efficient. Below we have discussed some of the key advantages.

    • It allows flexible object initialization with simplified code, improving readability and maintainability.
    • It prevents Object Creation with Invalid Data, where it allows valid data only.
    • It reduces the need for setter functions and supports constructor overloading.
    • It also provides better memeory management (with Dynamic Memory Allocation), enforces Default Values for Missing Arguments, and overall improves code performance.
  • C++ – Default Constructors

    Constructors are functions of a class that are executed when new objects of the class are created. The constructors have the same name as the class and no return type, not even void. They are primarily useful for providing initial values for variables of the class. The two main types of constructors are default constructors and parameterized constructors.

    Default Constructors

    C++ default constructors do not take any parameters. If a default constructor is not provided by the programmer explicitly, then the compiler provides a implicit default constructor. In that case, the default values of the variables are 0.

    Syntax

    Here is the following syntax for a default constructor:

    classMyClass{public:MyClass(){// Default constructor body}};

    Example of Default Constructor

    A program demonstrating default constructors is given as follows:

    #include <iostream>usingnamespace std;classDemoDC{private:int num1, num2 ;public:DemoDC(){
             num1 =10;
             num2 =20;}voiddisplay(){
          cout<<"num1 = "<< num1 <<endl;
          cout<<"num2 = "<< num2 <<endl;}};intmain(){
       DemoDC obj;
       obj.display();return0;}

    Output

    num1 = 10
    num2 = 20
    

    Explanation

    • Here first created the Object of type DemoDC(), where the default constructor automatically invoked.
    • It initializes the class members num1 and num2 with the values 10 and 20.
    • Then the display() method prints these values.

    Implicit vs Explicit Default Constructors

    In object-oriented programming (OOP), depending on how a default constructor is declared, it can be divided into two categories, implicit and explicit.

    1. Implicit Default Constructor

    An implicit default constructor is a constructor that is automatically called by the complier when an object is created, it may also be invoked if the user passes arguments that would be convertible into the constructor’s parameters.

    Syntax

    classMyClass{int x;double y;};intmain(){
       MyClass obj;// Implicit default constructor is called}

    2. Explicit Default Constructor

    An explicit default constructor is the one where the constructor is not allowed to be called implicitly by the compiler when performing automatic type conversions or copy-initialization. In other words, the user can only call directly when providing a matching argument.

    Syntax

    classClassName{public:explicitClassName(int x =10);// Explicit constructor};

    Default Constructor vs Parameterized Constructor

    A default constructor is a constructor, which takes no parameter or has all its parameters set to default values.

    Whereas a parameterized constructor is a constructor, which takes one or more arguments. It allows users to pass values during the creation of an object, which is further used for the initialization of an object.

    In this tutorial, we will basically learn about the default constructor.

    Syntax

    Here is the following Syntax for the Default constructor.

    classClassName{public:// Default constructorClassName(){// Initialization or setup code}};

    Here is the following example for the Default constructor.

    Explanation

    • In this example, first, we created the class named DemoDC.
    • In class, two private member variables num1 and num2 of type int are declared.
    • then a default constructor is defined for the DemoDC class. Where this constructor is automatically called when an object of the class is created.
    • In this constructor num1 and num2 are initialized to 100 and 20 respectively.
    • In int main(), an object of the class DemoDC is created, which triggers the default constructor DemoDC().
    • And obj.display() displays the values of num1 and num2.

    When Default Constructor Called?

    A default constructor is called in various situations, mainly when an object is created without arguments. Here we will discuss more situations where the default constructor is invoked.

    • When an Object is created without arguments.
    • When a class does not explicitly define any constructors.
    • In derived classes, if the base class has a default constructor.
    • When dynamically allocating an object.

    Overloading the Default Constructor

    In C++, overloading the default constructor is said to create multiple constructors within a class, where each constructor has a different parameter list, allowing for different ways of initializing objects.

    Example

    Here is the following example for Overloading the default Constructor in C++.

    #include <iostream>usingnamespace std;classMyClass{public:int a, b;// Default constructor (no arguments)MyClass():a(0),b(0){
             cout <<"Default constructor called"<< endl;}// Overloaded constructor with one argumentMyClass(int x):a(x),b(0){
             cout <<"Overloaded constructor (1 argument) called"<< endl;}// Overloaded constructor with two argumentsMyClass(int x,int y):a(x),b(y){
             cout <<"Overloaded constructor (2 arguments) called"<< endl;}voiddisplay(){
             cout <<"a: "<< a <<", b: "<< b << endl;}};intmain(){
       MyClass obj1;// Calls default constructor
       MyClass obj2(10);// Calls overloaded constructor (1 argument)
       MyClass obj3(10,20);// Calls overloaded constructor (2 arguments)
    
       obj1.display();
       obj2.display();
       obj3.display();return0;}

    Output

    Default constructor called
    Overloaded constructor (1 argument) called
    Overloaded constructor (2 arguments) called
    a: 0, b: 0
    a: 10, b: 0
    a: 10, b: 20
    

    Explanation

    • Here, MyClass() is the default constructor, where initializing a and b to 0.
    • MyClass(int x) is the constructor with one argument, where initializing a and b to x and 0 respectively.
    • MyClass(int x, int y) is the constructor with two arguments, where initializing both a and b to x and y respectively.