Explicit Constructor in C++

Discussion in 'C++' started by Mridula, Jan 25, 2010.

  1. Mridula

    Mridula New Member

    Joined:
    Mar 5, 2008
    Messages:
    316
    Likes Received:
    19
    Trophy Points:
    0
    Occupation:
    S/w proffessional
    Location:
    Bangalore
    Constructors are functions with the same name as the class. They are used to create the instance of a class. They are provided default by the compiler. But still user can have his/her own constructor declared. We can have a constrctor with a single parameter and use this kind of constructor for doing type conversion or implicit conversion.

    For Example:

    The code



    Code:
    #include<iostream.h>
    
    class A 
    {
      int data;
    
    public:
      A(int a):data(a)
      {
          cout<<"A::Construcor...\n";
          cout<<"value of data :="<<data<<endl;
      };
    };
    
    
    int main()
    {
      A a1 = 37;
    
      return (0);
    }
    
    ./a.out
    A::Construcor...
    value of data :=37
    
    A declaration like below in this example is called as Impliicit Conversion and calls A(int a) constructor to create an A object from the integer value:

    A a1 = 37;

    If you define the single parameter as an object of another class, then that constructor allows the compiler to perform an automatic type conversion, which is also called as Constructor Conversion.

    For Example:

    The code



    Code:
    #include<iostream.h>
    
    class A 
    {
    
    public:
      A() 
      {
          cout<<"A::Construcor...\n";
      };
    };
    
    class B
    {
        
    public:
        
        B(const A& aObj)
        {
          cout<<"B::Construcor...\n";
        };
    };
    
    void display(B bObj)
    {
        cout<<"function display...\n";      
    }
    
    
    int main()
    {
      A a;
      
      //Call display with A object i.e. a1
      display(a);
    
      return (0);
    }
    
    ./a.out
    A::Construcor...
    B::Construcor...
    function display...
    
    In this example, when compiler sees display() called with a A object, it looks at the declaration of display() and finds out it needs B object. Then it looks to see, if there is any way to get a B object from A object and it finds B class's single parameter constructor, which it implictly calls. This results in handing over B 's object to function display().

    This one way, may prevent us from overloading display() function for 2 different objects here!! But if you look at the efficiency of function display() - it degrades as it implicitly calls B's constructor, before really calling the display() function and this could be a concern here.

    Lets see another example.

    The code



    Code:
    #include<iostream.h>
    
    class A 
    {
      int data;
    
    public:
      A(int a):data(a)
      {
          cout<<"A::Construcor...\n";
      };
    
      friend void display(A obj);
    };
    
    void display(A obj)
    {
        cout<<"Valud of data in obj :="<< obj.data<<endl;
    }
    
    int main()
    {
      //Call display with A object i.e. a1
      display(5000);
    
      return (0);
    }
    
    output
    -----------
    ./a.out
    A::Construcor...
    Valud of data in obj :=5000
    
    When you look at this example, it is very confusing!! Though the function display expects an object of class A, but passing an integer value 5000 seems to be working and it gets converetd to A obj and then calls class A(int a) constructor.

    To avoid all such confusions that happens with Implicit Conversion and Constructor Conversion, we can use explicit ketword in constructor declaration. This forces the compiler not to do an implicit conversion and throws an error for this kind of code. And thus make sures the constructor is explicitly called with the right syntax. This keyword is used only for the constructors.

    Now lets take the first example and make the constructor explicit and try to call as below:

    The code



    Code:
    #include<iostream.h>
    
    class A 
    {
      int data;
    
    public:
      explicit A(int a):data(a)
      {
          cout<<"A::Construcor...\n";
          cout<<"value of data :="<<data<<endl;
      };
    };
    
    
    int main()
    {
      A a1 = 37;
    
      return (0);
    }
    
    We will get the below Compiler Error:
    ---------------------------------------
    explicit1.cc: In function `int main()':
    explicit1.cc:18: error: conversion from `int' to non-scalar type `A' requested
    
    Same way, we can avoid Constructor Conversion in above example by making B's constructor as explicit as shown below:

    explicit B (const A& aObj)

    But explicit on a constructor with multiple arguments has no effect, since such constructors cannot take part in implicit conversions. However, explicit will have an effect if a constructor has multiple arguments and all but one of the arguments has a default value.

    For Example:

    The code



    Code:
    #include<iostream.h>
    
    class A 
    {
      int data1;
      int data2;
      char* name;
    
    public:
      A(int a, int b=10, char* c = "mridula"):data1(a), data2(b), name(c)
      {
          cout<<"A::Construcor...\n";
      };
    
      friend void display(A obj);
    };
    
    void display(A obj)
    {
        cout<<"Valud of data1 in obj := "<< obj.data1<<endl;
        cout<<"Valud of data2 in obj := "<< obj.data2<<endl;
        cout<<"Valud of name in obj  := "<< obj.name<<endl;
    }
    
    int main()
    {
      //Call display with A object i.e. a1
      display(100);
    
      return (0);
    }
    
    Output:
    ----------
    ./a.out
    A::Construcor...
    Valud of data1 in obj := 100
    Valud of data2 in obj := 10
    Valud of name in obj  := mridula
    
    In this example, though we have multiple argument constructor
    A(int a, int b=10, char* c = "mridula") (all defaulted argument but one), but still there seems to be an implicit conversion happening from type int to A's object.

    As said above, it is better to use explicit for such constructor declaration too to avoid any such implicit conversions.

    Declare the multiple argumented constructor in the above example as below to avoid implicit conversion:

    explicit A(int a, int b=10, char* c = "mridula");

    Hope this helps !!
     
    shabbir likes this.
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice