Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Classes


Contents

Constructors

A constructor is a method that is called for us to initialize the variables of a class and any other initialization work that we may want to do. Let's try to write our own method called "initialize" .
File: demo1.cpp
#include <iostream>
using namespace std ;

class Demo
{
  public:
    int x1 ;
    int x2 ;
    void initialize()
    {
        x1 = 5 ;
        x2 = 10 ;
        cout << "Inside the initialize method." << endl ;
    }
};

int main()
{
    Demo demo1Obj  ;
    demo1Obj.initialize() ;
    cout << demo1Obj.x1 << " : " << demo1Obj.x2 << endl ;
    return(0) ;
}
Output:
[amittal@hills default]$ ./a.out
Inside the initialize method.
5 : 10
We have defined a method to do the initialization. To keep things simple all the data variables are defined as "public" . In the main method we can call "initialize" and set the values of our data variables. Even though this does what we want it to; it is not very elegant. What if we forget to call the "initialize" method ? The constructor feature provides a better method.
Let us write the above program using a constructor.

File: demo2.cpp
#include <iostream>
using namespace std ;

class Demo
{
    public:
    int x1 ;
    int x2 ;
    Demo()
    {
        x1 = 5 ;
        x2 = 10 ;
        cout << "Inside the initialize method." << endl ;
    }
};
int main()
{
    Demo demo1Obj  ;
    cout << demo1Obj.x1 << " : " << demo1Obj.x2 << endl ;
    return 0 ;
}
We have defined the constructor as:

  Demo()

The constructor has the same name as the class and
does not have a return type. Why not ? We are not
calling the constructor and getting a return value.
Rather the constructor is called for us when we create
the object at the line:

  Demo demo1Obj  ;

We can confirm that by the following program:


File: demo3.cpp
#include <iostream>
using namespace std ;

class Demo
{
    public:
     int x1 ;
     int x2 ;
     Demo()
      {
          x1 = 5 ;
          x2 = 10 ;
          cout << "Inside the constructor method." << endl ;
      }
};

int main()
{
    cout << "Before creating the object." << endl ;
    Demo demo1Obj  ;
    cout << "After creating the object." << endl ;
    cout << demo1Obj.x1 << " : " << demo1Obj.x2 << endl ;
}
Output:
[amittal@hills default]$ ./a.out
Before creating the object.
Inside the constructor method.
After creating the object.
5 : 10
As we can see the constructor method got called at the time the object was created. The same applies to dynamic creation of objects.
File: demo4.cpp
#include <iostream>
using namespace std ;
class Demo
{
    public:
     int x1 ;
     int x2 ;
     Demo()
     {
         x1 = 5 ;
         x2 = 10 ;
         cout << "Inside the initialize method." <<
         endl ;
      }
};

int main()
{
    cout << "Before creating the object." << endl ;
    Demo* demo1Obj  ;
    demo1Obj = new Demo() ;
    cout << "After creating the object." << endl ;
    cout << demo1Obj->x1 << " : " << demo1Obj->x2 << endl ;
    delete demo1Obj  ;
    return 0 ;
}
Output:
[amittal@hills default]$ ./a.out
Before creating the object.
Inside the initialize method.
After creating the object.
5 : 10
The syntax for creating a dynamic object is :
new Demo()
If we don't have a constructor for our class then the compiler will create one for us that will not have any arguments or a body for that matter. The default constructor does not do anything .
We can also define constructors with arguments.

File: demo5.cpp
#include <iostream>
using namespace std ;

class Demo
{
    public:
      int x1 ;
      int x2 ;
    Demo(int x1P, int x2P)
     {
         x1 = x1P  ;
         x2 = x2P ;
         cout << "Inside the construtor method." << endl ;
      }
};

int main()
{
    Demo demo1Obj  ;
}
$ g++ demo5.cpp ; ./a.exe
demo5.cpp: In function ‘int main()’:
demo5.cpp:19:14: error: no matching function for call to ‘Demo::Demo()’
   19 |         Demo demo1Obj  ;
      |              ^~~~~~~~
demo5.cpp:9:9: note: candidate: ‘Demo::Demo(int, int)’
    9 |         Demo(int x1P, int x2P)
We have a single constructor that takes arguments and we try to create an object without supplying any arguments to the constructor. However the compiler sees that we have a constructor that takes arguments and do not have a constructor that does not take any arguments. The compiler in this case will not create the default constructor without any arguments and will force us to use the constructor that we have defined that takes arguments. We can correct the problem by supplying the arguments at the time of creation.
File: demo6.cpp
   #include <iostream>

   using namespace std ;
   class Demo
   {
       public:
       int x1 ;   int x2 ;
       Demo(int x1P, int x2P)
       {
           x1 = x1P  ;
           x2 = x2P ;
           cout << "Inside the construtor method." << endl ;
       }
  };

int main()
{
    Demo demo1Obj( 4 , 6 )   ;
}

$ g++ demo6.cpp ; ./a.exe
Inside the construtor method.

In the above case the compiler will not create a default constructor without any arguments.

Overloaded Constructors

We can create several different constructors with different arguments for a single class.
File: demo7.cpp
  #include <iostream>

  using namespace std ;
  class Demo
  {
      public:
      int x1 ;
      int x2 ;
      Demo(int x1P, int x2P)
      {
          x1 = x1P  ;
          x2 = x2P ;
          cout << "Inside the construtor method." << endl ;
       }
       Demo()
       {
           cout << "Inside the default construtor." << endl ;
       }
};

int main()
{
    Demo demo1Obj( 4 , 6 )   ;
    Demo demo2Obj   ;
    return 0 ;
}
Output:
[amittal@hills default]$ ./a.out
Inside the construtor method.
Inside the default construtor.


Default Values

We can also have constructors with arguments that take on default values.
File: demo8.cpp
#include <iostream>

using namespace std ;
class Demo
{
    public:
      int x1 ;
      int x2 ;
    Demo(int x1P = 4, int x2P = 5)
    {
         x1 = x1P  ;
         x2 = x2P ;
         cout << "Inside the construtor method." << endl ;
    }
    Demo()
    {
        cout << "Inside the default construtor." << endl ;
    }
};

int main()
{
    Demo demo1Obj( 4 , 6 )   ;
    Demo demo2Obj   ;

    return 0 ;
}
$ g++ demo8.cpp ; ./a.exe
demo8.cpp: In function ‘int main()’:
demo8.cpp:24:14: error: call of overloaded ‘Demo()’ is ambiguous
   24 |         Demo demo2Obj   ;
We need to be careful that the compiler does not get confused. In the above case the second object "demo2Obj" can be constructed by either of the 2 constructors that we have defined.
Rewriting the above as:

File: demo9.cpp
#include <iostream>
using namespace std ;
class Demo
{
    public:
    int x1 ;
    int x2 ;
    Demo(int x1P = 4, int x2P = 5)
    {
        x1 = x1P  ;
        x2 = x2P ;
        cout << "Inside the construtor method." << endl ;
    }
};

int main()
{
    Demo demo1Obj( 4 , 6 )   ;
    Demo demo2Obj   ;

    return 0 ;
}
Now the second object uses the default values since we are not supplying any arguments in the constructor. If we have defined at least one constructor then the default constructor is not constructed by the system.

Exercise:

1) Refer to your class "vehicle" from previous exercise that contains the properties "weight" , "top speed" and "number of wheels" and a method to print the properties.
Place an include guard in the header file. Create a constructor to set the 3 values of "weight", "top speed" and "number of wheels"
Create 2 objects of type vehicle; one that is on the stack and another that is on the heap.