Use of Explicit Constructor in Our Class

Written by Raza on. Posted in C++

C++ is a very powerful and fast language. One potential danger because of this is the ability of language to call methods and convert data into other types automatically without asking the programmer. So the programmer has an added responsibility of keeping an eye on the compiler and watch out for all such errors. One such common problem is the implicit conversion through a constructor. To avoid that, we use an explicit constructor in C++. Let us see a sample code for that and then I shall explain to you what actually happens. 

We are working yet again with our Fraction class and I have made some additions to its interface. Here is its declaration.

</p>
<p>class Fraction<br />
{<br />
.  private :<br />
.   int num ;<br />
.   int den ;<br />
.  public :<br />
.   Fraction () ;<br />
.   Fraction (const int , const int) ;<br />
.   Fraction (const int) ;<br />
.   Fraction operator + (const Fraction&amp;) ;<br />
} ;</p>
<p>.<br />
Fraction :: Fraction (const int number)<br />
{<br />
.  num = number ;<br />
.  den = 1 ;<br />
}</p>
<p>.</p>
<p>int main ()<br />
{<br />
.  Fraction f1 (3, 2), f2 (5)</p>
<p>.  f1 + 2 ;<br />
}</p>
<p>

In the declaration, the new addition is a constructor which takes only one integer parameter as it only takes a numerator. For example, if I create a fraction with value 5, it is certainly equal to 5/1. Denominator is automatically made 1 inside this constructor.

Now forget about this constructor and come over to the code in main.

I have created two object f1 and f2 and now want to add them up. By mistake, I have written f1+2 instead of f1+f2. This typo can happen quite easily without notice. But I had thought that compiler would give me error if I make such a mistake because overloaded function for addition takes an integer as a parameter. But I was wrong too far!

In fact this code compiles and executes perfectly without me being noticing what the hell has happened. Now I shall tell you why this code compiler and runs perfectly. When you send the integer as argument to the addition operator, compiler goes over to that function and tries to match its data types with the parameter of the function. It finds that they mismatch, surely. But it does not give error. What it does is that it goes all over the program and checks if there is any way I could convert this integer thing into an object of this class. It finds a constructor which takes a single parameter, the one I talked about above. You are familiar with typecasting now. So it automatically calls this constructor and converts this integer into a temporary object of Fraction class without even your permission.

This may look quite absurd to you but it actually happens, and that is what is happening in our program right now. This type of conversion is known as implicit conversion and at times it could be pretty dangerous. It is supported in C++ language because it proves to be helpful as well and sometimes we want to convert different data types into user defined objects automatically. But if we do not want to do so, we are doomed if implicit conversion happens.

To avoid such situation, we use a keyword explicit before the prototype of the constructor. The constructor now becomes an explicit constructor. It means that unless or until you call the explicit constructor explicitly yourself, it won’t be called by itself. In our program, if I make the mistake and do f1+2, now compiler would give me error because of the explicit constructor.

Rule of the thumb is; whenever there is a constructor in your class which takes only one parameter, make that constructor an explicit constructor. That parameter has to be of non-class type like int, char, etc. Obviously copy constructor would not be included in that and you cannot make copy constructor an explicit constructor. The reason is obvious as copy constructor is called automatically at three occasions. Read here when a copy constructor is called. Still if you make copy constructor an explicit constructor, you cannot initialize an object and return it from a function by value. So better not do that.

Tags: , , , , , ,