C++ constructors and destructors

This post was written and published to explain the following two C++ programming topics:

C++ Constructor

Constructors are member functions of a class having the same name as the class in which they are defined. A "constructor" is used when we need it to be called automatically when a class object is created.

The general form to create a constructor in C++ should be:

class className
{
   .
   .
   .
   className()
   {
      .
      .
      .
   }
   .
   .
   .
};

Consider the following program as an example of constructor in C++.

#include <iostream>
using namespace std;
class myClass
{
   public:
      int num;
      myClass()
      {
         cout<<"----Welcome to the Portal----\n\n";
      }
};
int main()
{
   myClass ob;

   cout<<"Enter a number: ";
   cin>>ob.num;

   cout<<"You entered: "<<ob.num;

   cout<<endl;
   return 0;
}

The following snapshot shows the initial output produced by the above example program:

c++ constructor example

As you can see from the above output, the text "---Welcome to the Portal---" is displayed when an object "obj" is created of the class "myClass,"  because I defined a constructor inside the class that outputs this text. Now just type a number, say 20, and hit the ENTER key to produce the following output:

c++ constructor program

Note: Constructors and destructors have no return type, not even void.

Need for constructors in C++

In C++, the structures and arrays that are being declared can have their contents initialized at the same time. Take, as an illustration, the following snippet from the code:

struct Student
{
   int id;
   float marks;
};
int main()
{
   Student s1 = {0, 0.0};
   int a[5] = {1, 2, 3, 4, 5};
   .
   .
   .
}

However, this kind of initialization does not work for classes because the members of a class each have their own access specifiers associated with them. They might not be accessible to people in other parts of the world (outside their class). There is potentially more than one answer to this problem. If we define a member function within the class to provide initial values, say we call it init(), as shown in the following example:

class Student
{
   private:
      int id;
      float marks;
   public:
      void init()
      {
         id = 0;
         marks = 0.0;
      }
};
int main()
{
   Student s;
   s.init();      // initialize it
   .
   .
   .
}

See, even though there is now a single function called "init()" that can supply initial values, the programmer must still actively call it in order to initialize the object. This is because init() is the only function that can do so. In other words, the sole responsibility for initiating something lies with the person who wrote the program.

What happens if the programmer forgets to call the init() function?
If this is the case, the object is likely to be corrupted with garbage, which could wreak havoc on your program. The question now is, what exit can we take?

The solution is straightforward: remove the obligation of initialization from the programmer and place it instead on the shoulders of the compiler, since the compiler is the only one who is aware of the precise moment when objects are created. The initialization function will be called whenever an object is created by the compiler, which means that the object will always have its state properly set.

If the initialization function has the same name as the class, i.e. it is a constructor, then the responsibility is passed on to the compiler. However, this is the only circumstance in which the compiler will accept this responsibility.

Note: A constructor is required for a class in order for the compiler to be able to immediately begin the process of initializing an object once it has been created. If a class constructor has been defined, it will be invoked whenever an object of that class is created by a piece of software.

Note: Constructors can be either without or with parameters.

Constructor Overloading in C++

The function (constructor) of a class, like any other function, can be overloaded so that an object can be initialized with different numbers and types of initial values. Consider the following example program:

#include <iostream>
using namespace std;

class DEPOSIT
{
   long int principal;
   int time;
   float rate;
   float totalAmount;

public:
   DEPOSIT();
   DEPOSIT(long p, int t);
   DEPOSIT(long p, float r);
   DEPOSIT(long p, float r, int t);

   void calculateAmount(void);
   void display(void);
};

DEPOSIT :: DEPOSIT()
{
   principal = time = rate = 0.0;
}
DEPOSIT :: DEPOSIT(long p, float r, int t)
{
   principal = p;
   rate = r;
   time = t;
}
DEPOSIT :: DEPOSIT(long p, int t)
{
   principal = p;
   time = t;
   rate = 0.08;
}
DEPOSIT :: DEPOSIT(long p, float r)
{
   principal = p;
   time = 2;
   rate = r;
}
void DEPOSIT :: calculateAmount(void)
{
   totalAmount = principal + (principal * time * rate) / 100;
}
void DEPOSIT :: display(void)
{
   cout << "Principal Amount: $" << principal << "\n";
   cout << "Period of investment: " << time << " years\n";
   cout << "Rate of interest: " << rate << "\n";
   cout << "Total Amount: $" << totalAmount << "\n";
}

int main()
{
   DEPOSIT d1;
   DEPOSIT d2(4000, 1);
   DEPOSIT d3(3000, 0.12f);
   DEPOSIT d4(2000, 0.07f, 2);

   d1.calculateAmount();
   d2.calculateAmount();
   d3.calculateAmount();
   d4.calculateAmount();

   cout << "Object 1\n";
   d1.display();

   cout << "\nObject 2\n";
   d2.display();

   cout << "\nObject 3\n";
   d3.display();

   cout << "\nObject 4\n";
   d4.display();

   cout << endl;
   return 0;
}

The output should be:

Object 1
Principal Amount: $0
Period of investment: 0 years
Rate of interest: 0
Total Amount: $0

Object 2
Principal Amount: $4000
Period of investment: 1 years
Rate of interest: 0.08
Total Amount: $4003.2

Object 3
Principal Amount: $3000
Period of investment: 2 years
Rate of interest: 0.12
Total Amount: $3007.2

Object 4
Principal Amount: $2000
Period of investment: 2 years
Rate of interest: 0.07
Total Amount: $2002.8

There are four constructors in the preceding example, which are as follows:

C++ Destructor

The destructor is used to destroy the instances. In other words, destructors destroy the object that has been created by a constructor. Just like the constructor, destructor is also a member function of the class with the same name as the class. The only difference is that we need to add the "tilde (˜)" sign before the destructor. As an example:

#include <iostream>
using namespace std;
class myClass
{
   public:
      int num;
      myClass()       // constructor
      {
         cout<<"----Welcome to the Portal----\n\n";
      }
      ~myClass()      // destructor
      {
         cout<<"\nDestructor at work...\n";
      }
};
int main()
{
   myClass ob;

   cout<<"Enter a number: ";
   cin>>ob.num;

   cout<<"You entered: "<<ob.num;

   cout<<endl;
   return 0;
}

The snapshot below depicts a sample run of the above program with user input of 124:

c++ destructor example

Need for destructors in C++

The constructor may allocate resources for use during the construction of an object. For example, a constructor may have opened a file and assigned it a memory area. A constructor may have also allocated memory to other objects.

Before the object can be destroyed, the allocated resources must be released. Whose responsibility is it now?
A destructor volunteers for this task and automatically performs all clean-up tasks (such as closing a file, deallocating, and releasing memory areas).

C++ Quiz


« Previous Tutorial Next Tutorial »