Constructor & Destructor

Constructor :
As name suggest, it construct an object. Constructor is used to initialize the data members of a class.
Consider a class below:

#include <iostream>
#include <string>
using namespace std;
class employeeData {
unsigned int m_salary;
char* m_name;
public:
~ employeeData() { //Destructor
if (m_name) {
delete []m_name;
}
}

employeeData() { // default constructor
cout << “employeeData default C’tor” << endl;
m_salary = 0;
m_name = NULL;
}

employeeData(unsigned int salary, char* name) {

//Parameterized constructor
cout << “employeeData parameterized C’tor” << endl;
m_salary = salary;
unsigned int len = strlen(name);
m_name = new char[len +1];
strncpy(m_name, name, len);
m_name[len+1] = ‘\0’;
}
};

In default-constructor (constructor without any arguments) m_name and m_salary is initialized to NULL and zero respectively.

In parameterized constructor, memory is allocated for m_name (for pointer data member) based on the name length using new operator and then copy the content. Similarly, m_salary is initialized to salary.

If user does not define constructor, compiler provides a constructor for a class. Compiler provided constructor does not initialize the data members but it initialize the hidden virtual pointer to V-table needed for polymorphism to work when one or more virtual member function is present in a class.

Similarly, compiler provides the Copy constructor and Assignment operator if user does not define it in a class.

Virtual constructor is not possible in C++.
     When we create an object, C++ first initialize(construct) its base class 
     then derive class. Now if we make base class constructor virtual, this
     means we are telling to compiler to initialize the derived class first
     before base class which is completely wrong. That is why C++ does not
     allow virtual constructor.
     To understand this, you can take an example of building. First, we create
     foundation, then we start building it. Not the vice-versa way

Data member in the constructor can be initialized using Initializer List as well.

Don’t call virtual function in the constructor because you won’t get what you expect. Let us understand with an example.

class base {
public:
    base() {
        display();
    }
    virtual void display() {
        cout << "Display base" << endl;
    }
};

class derived: public base
{
public:
    derived() {}
    void display() {
        cout << "Display derived" << endl;
    }
};

int main() {
    derived d;
    return 0;
}

In this, we have called virtual function in the base class constructor. So when derived d, base class constructor is called first then derived class constructor. In base class constructor, display of base class is called not of derived.
During base class constructor of derived object, type of the object is base class since derived class it not initialized yet. so it calls base class function.
Constructor can be overloaded i.e. constructors with different type or number of arguments is possible

Destructor
As name suggest, it destruct the object. Destructor is used to clean the data members of a class.

In destructor, user should delete the pointer member variable if any as seen in the above class.

If user does not define destructor, compiler provides a destructor for a class. Compiler provided destructor does not take care of deleting pointer member variable if any and hence results in memory leak. User must define destructor for a class in order to avoid memory leak.

Virtual destructor is possible in C++. In fact, as a thumb rule, keep the base class destructor always virtual even if there is no virtual member function in the class.

Below example explains how without using virtual destructor, memory leak can occur.

#include <iostream>
using namespace std;
class person {
public:
person(){}
virtual ~person() {
cout << “person D’tor” << endl;
}
};

class employee : public person {
public:
employee (){}
~ employee () {
cout << “employee D’tor” << endl;
}
};

class developer : public employee {
public:
developer (){}
~ developer () {
cout << “developer D’tor” << endl;
}
};

int main() {
person* p = new employee();
delete p;
return 0;
}


Output:
employee D’tor
person D’to

If base class destructor is not virtual in the above scenario, then output will be:
person D’tor
employee Destructor is not called. As a result, it can lead to memory leak if any pointer data member present in employee class for which memory is allocated in constructor or through any member function.

In addition, you can see there is no virtual member function present in the any of the above class still virtual destructor is required.

We can throw an exception from the destructor but C++ discourage to do that since it can lead to termination of program or undefined behavior.
As a thumb rule, never thrown an exception from destructor. if somehow destructor thrown an exception, try to catch in the destructor itself.

Don’t call virtual function in destructor. Same reason as mention for constructor.

Unlike constructor, we cannot overload destructor i.e. only one destructor will be present for a class.

Related posts