9 Constructor

Jyoti Pareek

epgp books

Introduction

 

In C++, all the objects are created using a special member function known as Constructor. The task of this function is to allocate the memory for the object and initialize the object.

Before we see what is Constructor, first we need to understand the importance of Object initialization.

 

Object Initialization :

 

We have seen how variables can be initialized at the time of declaration, an example of this is:

int sum = 0 ;

Here variable ‘sum’ is declared and initialized with the value 0.

 

Variable initialization is important so that we do not accidently use a variable without assigning a value to it. Similarly Object initialization is important so that we do not accidently use an object before initializing the data members of the object.

 

Now the question is how we can initialize the data members of object. This functionality can be achieved by defining some member function and calling that function whenever we declare a class object as shown in the example below:

 

Class Time

 

{

private:

int seconds;

int minutes;

int hours;

 

public:

void init()

{

hour=12;

minute=0;

seconds=0;

}

};

void main()

{

Time start_time , end_time;

start_time.init ();

end_time.init ();

}

Here we observe that this process of initialization of object is different than that of initialization of variable of standard data type. In our example data members of object are not initialized at the point of declaration, rather we are assigning initial values to data members later by invoking same member function meant for the job explicitly.

 

This makes the process of initialization less effective. As it require the programmer to remember that for each Time object , function init() must be invoked before the operation is performed on the object. Programmers often forget these minor details.

 

So it is desirable that we are able to initialize data member of object of declaration as we do with standard data type. So now the question is:

 

Can we initialize objects at the time of creation?

 

The answer is YES.

 

This can be achieved with the help of a special member function known as Constructor.

 

 

 

What is Constructor ?

 

Constructor is a special member function of a class, special in the sense that unlike other functions constructor has the following characteristics:

 

  • It has no return type (not even void)
  • It has the same name as its class.
  • Called automatically at the time of object creation.

Constructors are useful in many situations. The typical uses of constructor are :

  • Initializing class variables with a specific default value
  • Initializing class variables with a specific value provided by user
  • Allocating dynamic storage

In fact every class must have a constructor for its object creation. But if we see our Time class, it does not have constructor. Then how does our objects start_time and end time are created? Whenever we do not define constructor, computer provides a default constructor. And in our program our start_time and end_time object get constructed with compiler provided default constructor.

 

If no constructor is defined in the class, C++ compiler provides constructor for every class but compiler provided constructor just create the object but do not initialize the data members. For the initialization purpose we can also provide user defined constructor. If we want our objects to start out with meaningful values, we must create our own constructor.

 

Let’s see how to define a constructor –

 

Constructors are defined as any other member function of the class.

 

Syntax:

classname(paramenter list)

 

{

// constructor Defintion

}

 

Example:

 

class Time

{

private:

int seconds;

int minutes;

int hours;

 

public:

 

Time()//constructor

{

cout<<”Constructor invoked” ;

seconds =0;

 

minutes=0;

hours=0;

}

 

};

 

void main()

{

Time star_timet ;// constructor is invoked implicitly

 

}

Here when any object of Time class is created the constructor is invoked implicitly. So now no need to define a separate functions like init() to initialize the objects. Also there is no possibility of forgetting to initialize object before its use.

 

Constructor like other member function can be defined inline or outline. Constructor can be defined in different flavors. We will see them all one by one

 

Default Constructor:

 

Constructor without any parameters is known as default constructor. It is also known as 0-argument constructor. In previous example the constructor Time() is default constructor.

 

Default constructor can be either

  • – Compiler Defined or
  • – User Defined

Compiler Defined Default constructor:

 

C++ run time system always invokes the constructor of a class when its objects are created. This is true even if no constructor is defined for a class. In this case the run time system invokes the default constructor provided by the compiler (which performs no action). Compiler defined default constructor just create the object but do not initialize the data members with meaningful values.

 

Also when user does not provide any constructor then and only then the compiler automatically provides default constructor.

 

User Defined Default Constructor:

 

Compiler will provide a default constructor when no user defined constructor is available. But compiler defined default constructor cannot initialize objects with specific values. To initialize the data member with a specific default value, user must define a constructor and initialize the data member with some meaningful values within it. Once the user defined constructor is created, compiler will never create its own constructor. Let’s see the complete example of a user defined default constructor:

 

class Time

{

private:

int seconds;

int minutes;

int hours;

 

public:

Time()

{

seconds=0;

minutes=0;

hours=0;

}

 

};

main()

{

Time t1,t2;

}

 

Here when a Time object t1 and t2 are declared, the compiler will implicitly invoke the user defined constructor.

 

User defined constructors minimizes the work of programmer who otherwise has to initialize all the objects explicitly and also they reduces the error as the constructor will be invoked automatically at the time of object creation.

 

Parameterized Constructor:

 

Constructor with one or more arguments is known as parameterized constructor. When objects are required to be created with different initial values then parameterized constructors are used.Let’s see an example:

 

class Time

{

private:

int seconds;

int minutes;

int hours;

 

public:

 

Time(int s, int m, int h)

{

seconds=s;

minutes=m;

hours=h;

}

};

Here to initialize time object a parameterized constructor is created with 3 parameters. To invoke this constructor 3 integer values needs to be passed: Time t1(12,30,30) ;

 

Time t2(1,20,10) ;

 

Here two time objects will be created with different initial values. Parameterized constructor can be used when the initial values are different for different objects.

 

Constructor overloading (Multiple constructor):

 

A class can have multiple constructors provided they are different in terms of either number of arguments or type of arguments . This is same as function overloading as constructors are also member functions , they can also be overloaded as other member functions.

 

Let’s see an example :

 

class Time{

private:

int seconds;

int minutes;

int hours;

 

public:

 

//First Constructor (default constructor )

Time()

{

seconds=0;

minutes=0;

hours=0;

}

//Second Constructor (parameterized constructor with one parameter)

Time(int h)

{

seconds=0;

minutes=0;

hour=h;

}

//Third Constructor (parameterized constructor with three parameter)

Time(int s, int m, int h)

{

seconds=s;

minutes=m;

hour=h;

}

} ;

void main() {
Time t1; // First Constructor is invoked
Time t2(12); // Second Constructor is invoked
Time t3(12,30,20); // Third Constructor is invoked
}

 

Here we have declared 3 objects of class Time; the compiler will invoke the appropriate constructor looking at the number and type of parameter passed.

 

Note: It is a good practice to define a default constructor if we define any parameterized constructor , because once we define any constructor then compiler will not provide default constructor and objects without any parameter will not get constructed .

 

Let’s understand this with an example:

 

class Time{

// data members

 

public:

Time(int s, int m, int h)

{

…………

…………

}

 

}

 

Here the class has only one parameterized constructor , compiler will not create any default constructor now.

Time t1 (12, 30, 30) ;    // object is created using parameterized constructor

Time t2 ;  // Error, as no default constructor is available.

 

Default Arguments in Constructor :

 

Just like functions, default arguments can be passed in constructor . So in above example the second and third constructor can be combined if we pass default arguments :

 

Time(int h, int m=0 , int s=0)

{

………………….

…………………..

}

constructor will be invoked in all the following object creations:

 

Time t1(12) ;

Time t2(12,20);

Time t3(12,20,30);

 

Constructor and Member Initialization List (MIL)

 

MIL is the alternative way of initializing the class data member using constructor. Here the initialization is done outside the constructor body. Let’s see the example:

 

class Time{

private:

int seconds;

int minutes;

int hours;

public:

Time(int h, int m , int s) : hour(h) ,minute(m) , seconds(s)

{

//empty body

}

};

void main()

{

Time t(12,30,20);

 

}

 

The object ‘t’ is created by invoking the constructor having 3 parameters and the values are initialized using member initialization list (MIL). The list of members of MIL appears comma separated in the constructor function after a colon and before the constructor body. In the above example the values of hour, minute and seconds can be initialized in the constructor body also. Both the approaches will give the same outcome, but there are certain cases where MIL is must. Let’s see those cases:

 

1. Initializing const data member:

MIL is the only way to initialize const data member. The constant members cannot be initialized inside the constructor body.

 

Let us understand this with the help of an example:

 

class Emp

{

intemp_id;

const int ssn;

 

public:

Emp(int id, int no)

{

 

ssn = no;           // Error as ssn being the constant data member, assignment to it after declaration is not possible

 

emp_id=id

}

};

 

But this can be achieved with help of MIL as follows:

 

class Emp

{

intemp_id;

const int ssn;

 

public:

 

Emp(int id, int no):ssn(no)

{

emp_id=id

}

 

}

 

2. Initializing Reference member:

 

MIL is must to initialize reference members. Let’s the example:

 

class Stud{

 

int id;

int marks ;

int&a ;

public:

Stud(int i, int m)

{

id=i;

marks=m;

a = marks;      // Error as a being the reference data member, assignment to it after declaration is not possible

}

};

 

But this can be achieved with help of MIL as follows:

 

class Stud{

int id;

nt marks ;

int&a ;

public:

Stud(int i, int m) : a(marks)

{

id=i;

marks=m;

}

};

3. Initializing member objects:

 

If a class contains a data member which is an object of another class and that class does not contain a default constructor, then MIL is needed to initialize that member object. Let’s see the example:

 

class Door

{

int height;

int width;

 

public :

Door(int h, int w)

{

height=h;

width=w;

cout<<”Door constructor is invoked”;

}

};

 

Here the Door class has a single parameterized constructor.

class Room

{

Door d;

public:

Room(int h, int w): d(h,w)

{

cout<<”Room constructor is invoked”;

}

};

Here Room class has object of Door class. Therefore object of Room class will be constructed using two constructors – constructor of Room class and constructor of Door Class. Initializing Room class object through parameterized constructor would require the invocation of Door class parameterized constructor as well as values for Door data members have also been received in Room constructor. To do so MIL is the only way.

 

4.Performance

 

In certain cases MIL is more efficient. Let’s see this with the of an example: 

Let us add a default constructor in Door class and one more constructor in Room class as follows:

class Door

{

int height;

int width;

public :

Door()

{

height = 0;

width = 0;

}

Door(int h, int w)

{

height=h;

width=w;

cout<<”Door constructor is invoked”;

}

};

class Room

{

Door d;

public:

Room(Door r )

{

d = r;

cout<<”Room constructor is invoked”;

}

};

Here the constructor is having the parameter of Door class. So the following steps are executing:

 

1) The Door class default constructor is called for parameter “ r”

2) The assignment operator of Door is called inside the body of Room() constructor to assign d = r;

3) Destructor is called of class Door as object “r” goes out of scope.

Now let’s see the same constructor using MIL

 

Room(Door r ) : d (r)

{

cout<<”Room constructor is invoked”;

}

 

Here with MIL the steps are:

 

1) Copy constructor of “Door” class is called to initialize d (r).

2) Destructor of “Door” is called for “r” since it goes out of scope.

Thus we can see that with MIL one step of assignment is reduced. This is because MIL uses initialization instead of assignment.

 

 

MIL and the order of initialization:

 

 

The members are initialized in the order they are declared in the class and not in the order of MIL .

 

Example:

 

class Test{

int first;

int second;

int third;

 

public:

 

Test(int f, int s ,int t); third(t),first(f),second(s)

{

//empty body

}

};

 

In the above example the MIL contains the initialization in the sequence- third, first and second . But the members are initialized in the sequence of their declaration i.e. initialization will be done in the sequence – first, second and third.

 

Summary

  • In C++ all the objects are constructed using Constructer function.
  • If a class does not have any constructor , compiler provides a default constructor.
  • Constructor can also be overloaded just like other member functions.
  • Constructor is invoked implicitly by complier at the time of object creation. It is also possible to invoke them explicitly .
  • MIL is another way of initializing class object .

MIL is must to initialize const, reference and member objects

 

you can view video on Constructor

 

Additional References

 

1) Stanley Lippmann, “C++ Primer”, Pearson Education.

2) Bjarne Stroustrup, “The C++ Programming Language”, Pearson Education.

3) Scott Mayer, “Effective C++”, Addison Wesley.

4) Bhushan Trivedi , Programming with ANSI C++, 2/e , Oxford University Press.

5) Yashavant P. Kanetkar “Let Us C++” , Bpb Publications.

6) Abhiram G. Ranade, “An Introduction to Programming through C++” , McGraw Hill

7) Ellis and B. Stroustrup “Annotated C++ Reference Manual”, http://www.stroustrup.com/arm.html

8) Herbert Schildt, “Complete Reference C++”, McGraw Hill Publications.

9) Ashok Kamthane, “Object Oriented Programming with ANSI and Turbo C++”, Pearson Education

10) E Balaguruswami, “Object Oriented Programming With C++”, Tata McGraw Hill

11) “C++ FAQs”, Pearson Education.