Open In App

Default Methods in C++ with Examples

Last Updated : 29 Jul, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

If we write a class that has no methods in it, and the class does not inherit from another class, the compiler will add six methods to it automatically. The methods which can be automatically generated by the compiler are:
 

  1. Default Constructor: It is equivalent to an empty default constructor. The default constructor is a constructor which can be called with no arguments. It is called when an instance is created without initialization.
     
class_name object_name;
  1. Consider a class derived from another class with the default constructor, or a class containing another class object with default constructor. The compiler needs to insert code to call the default constructors of base class/embedded object.
     

CPP




#include <iostream>
using namespace std;
  
class Base {
public:
    // compiler "declares" constructor
};
  
class A {
public:
    // User defined constructor
    A()
    {
        cout << "A Constructor" << endl;
    }
  
    // uninitialized
    int size;
};
  
class B : public A {
    // compiler defines default constructor of B, and
    // inserts stub to call A constructor
  
    // compiler won't initialize any data of A
};
  
class C : public A {
public:
    C()
    {
        // User defined default constructor of C
        // Compiler inserts stub to call A's constructor
        cout << "C Constructor" << endl;
  
        // compiler won't initialize any data of A
    }
};
  
class D {
public:
    D()
    {
        // User defined default constructor of D
        // a - constructor to be called, compiler inserts
        // stub to call A constructor
        cout << "D Constructor" << endl;
  
        // compiler won't initialize any data of 'a'
    }
  
private:
    A a;
};
  
int main()
{
    Base base;
  
    B b;
    C c;
    D d;
  
    return 0;
}



Output: 

A Constructor
A Constructor
C Constructor
A Constructor
D Constructor

 

  1.  
  2. Destructor: It is equivalent to an empty destructor. It calls the superclass destructor and the destructors for member fields that are not of primitive type. The general form of declaring a destructor is follows: 
     
class_name::~class_name;
  1. Example for Destructor: 
     

CPP




#include <iostream>
using namespace std;
  
class Example {
  
private:
    int a, b;
  
public:
    // Constructor
    Example()
    {
        cout << "Constructor is called"
             << endl;
        a = 10;
        b = 20;
    }
  
    // Destructor
    ~Example()
    {
        cout << "Destructor is called"
             << endl;
    }
  
    // Member function
    void print()
    {
        cout << "a = " << a << endl;
        cout << "b = " << b << endl;
    }
};
int main()
{
    // Object created
    Example obj; // Constructor Called
  
    // Member function called
    obj.print();
  
    return 0;
}


  1.  
Output: 

Constructor is called
a = 10
b = 20
Destructor is called

 

  1.  
  2. Copy Constructor: Copy constructor is a constructor which can be called with a reference to a class instance as an argument. It is called when a new copy of an instance needs to be initialized either explicitly or implicitly by the compiler, e.g., when an instance is passed by value to a function or is returned by value. It initializes every instance member with a corresponding member of the constructor’s argument. 
    Below program demonstrates the use of Copy Constructor for better understanding. 
     
  3. Copy assignment operator: It is equivalent to an assignment operator that assigns every member of its argument to a corresponding member of this instance. Note that this may lead to calls to the member’s fields own copy assignment operators. 
     
MyClass t1, t2; 

// copy constructor is called
MyClass t3 = t1;

// copy assignment operator is called
t2 = t1;
  1. Example for Copy Constructor and Copy Assignment Operator: 
     

CPP




#include <iostream>
using namespace std;
  
class Line {
  
public:
    // constructor
    Line(int len);
  
    // copy constructor
    Line(const Line& obj);
  
    void display(void);
  
private:
    int* ptr;
};
  
Line::Line(int len)
{
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}
  
// Copy Constructor
Line::Line(const Line& obj)
{
    cout << "Copy constructor allocating ptr."
         << endl;
    ptr = new int;
  
    // copy the value
    *ptr = *obj.ptr;
}
  
void Line::display()
{
    cout << "Length of line: "
         << *ptr << endl;
}
  
// Main function for the program
int main()
{
  
    Line l1(10), l2(0);
  
    // Copy constructor called
    Line l3 = l1;
  
    // Copy assignment operator called
    l2 = l1;
  
    l1.display();
    l2.display();
    l3.display();
  
    return 0;
}


  1.  
  2. Move Constructor: The move constructor is a constructor which can be called with an rvalue reference to a class instance as an argument, typically ClassName(const ClassName&&). It is called when a new instance is initialized from a temporary object that typically is destroyed after initialization, e.g., when returning by value from a function or an explicit call as in ClassName new_instance(std::move(existing_instance)).
     
  3. Move Assignment Operator: C++11 defines two new functions related to move semantics: a move constructor, and a move assignment operator. Whereas the goal of the copy constructor and copy assignment is copied one object into another, the goal of the move constructor and move assignment is to move ownership of the resources from one object to another (which is much less expensive than making a copy). 
    Example for Move Constructor and Move Assignment Operator:
     

CPP




#include <iostream>
using namespace std;
  
struct S {
    int* p;
    int n;
  
    // Move Constructor
    S(S&& other)
        : p{ exchange(other.p, nullptr) }, n{ exchange(other.n, 0) }
    {
    }
  
    // Move Assignment Operator
    S& operator=(S&& other)
    {
  
        // move p, leaving nullptr in other.p
        p = exchange(other.p, nullptr);
  
        // move n, leaving zero in other.n
        n = exchange(other.n, 0);
        return *this;
    }
};


  1. Defining a move constructor and move assignment work equivalently to their copy counterparts. However, whereas the copy flavours of these functions take a const lvalue reference parameter, the move flavours of these functions use non-const r-value reference parameters.
     

Note: It is important to be aware of these functions. The problem is not in their existence but that we are not forced to write our own and may forget to so in cases where trivial copy/initialization will not work.
For example the following program prints 1 then -2. This is because the default copy assignment operator copies the raw pointer to b2. 
 

CPP




#include <bits/stdc++.h>
using namespace std;
  
class Buffer {
public:
    Buffer(int size, int* buffer)
        : size(size), buffer(buffer)
    {
    }
  
    int size;
    int* buffer;
};
  
int main()
{
    const int kBufSize = 2;
    int* buffer = new int[kBufSize]{ 1, 2 };
  
    Buffer b1 = Buffer(kBufSize, buffer);
    cout << b1.buffer[0] << endl;
  
    Buffer b2 = b1;
    b2.buffer[0] = -2;
    cout << b2.buffer[0] << endl;
  
    return 0;
}


Output: 

1
-2

 

Similar problems abound when using the default constructor and destructor—fields are not initialized, memory is not reclaimed, etc. In short, we should be aware that copying and initialization objects are our responsibility.
 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads