Monday 10 December 2012

Initialization Lists in C++

We all know, what happens when a class object is created; its Constructor is called. And, ofcorse that's not the end, it's base class constructor is also called. By default, the constructors invoked are the default ("no-argument") constructors. Moreover, all of these constructors are called before the class's own constructor is called.

So, with below piece of code,
class A 

public: 
     A()
     { 
          std::cout << "A's constructor" << std::endl; 
     } 
}; 

class B: public A
public: 
     B()
     { 
          std::cout << "B's constructor" << std::endl; 
     }
}; 

int main() 
{
     B obj1;
     return 0;
}
The object "obj1" is constructed in two stages: first, the A's constructor is invoked and then the B's constructor is invoked. The output of the above program will be to indicate that A's constructor is called first, followed by B's constructor. We all know this.

Why do this? There are a few reasons. First, each class should need to initialize things that belong to it, not things that belong to other classes. So a child class should hand off the work of constructing the portion of it that belongs to the parent class. Second, the child class may depend on these fields when initializing its own fields; therefore, the constructor needs to be called before the child class's constructor runs. In addition, all of the objects that belong to the class should be initialized so that the constructor can use them if it needs to.

Initialization List:
But what if you have a parent class that needs to take arguments to its constructor?
This is where initialization lists come into play. An initialization list immediately follows the constructor's signature, separated by a colon(:). Initialization List is another or a better approach for initializing the member variables (and base class objects) of a class upon construction of an instance of it's own.

Let's modify above code to demonstrate initialization list,

class A 

public: 
     A(int x)
     { 
          std::cout << "A's constructor is called with x = "<< x << std::endl;
     } 
}; 

class B: public A
public: 
     B() : A(100) //initialization list - construct A part of B
     { 
          std::cout << "B's constructor" << std::endl; 
     }
}; 

This is how you can construct and initialize base part of the child construct.

You can set-up order of constructors need to be called, before child constructor, separated by comma.
Like this,
class B: public A, public C
public: 
     B() : A(100), C(200)
     { 
          std::cout << "B's constructor" << std::endl; 
     }
}; 

The above call will be in sequential, as before B constructor, A part of B is initialized and then C part of B is initialized and after that only B's constructor is executed.

Here are interesting factors about initialization list:

> Initialization List is used to initialize both user defined data types (like embedded object of a class) and also primitive/built-in data types (like int, char).
Yes basically it is possible, look at below example,

class A 

public: 
     A(int x)
     { 
          std::cout << "A's constructor is called with x = "<< x << std::endl;
     } 
}; 

class B: public A
{
private:
     int x;
     int y;
public: 
     B() : A(100), x(25), y(50)
     { 
          std::cout << "B's constructor" << std::endl; 
     }
}; 

Above code initializes A part of B, then initializes two member variables 'x' and 'y' with constant values, before calling B's own constructor.

> Initialization List can appear irrespective of the place the constructor is defined.

> Initializing the member variables in the Initialization List is better than initializing them inside the body of the constructor of the class.

> Data members are initialized in the order they are declared, regardless of the order of their initialization.

> It is mandatory to initialize Reference Data Member in an Initialization List because it can not exist without being initialized.

> It is mandatory to initialize Constant Data Member in an Initialization List otherwise it would be constrructed with some junk values and we cannot initialize it later anywhere else.

> It is mandatory to construct and initialize, embedded class objects/base class objects in case of inheritance, in an Initialization List, if they do not themselves have a zero-argument/default constructor provided.

Great isn't it !!!!

No comments:

Post a Comment