Wrox Press C++ Tutorial
In the program above, we declared our Box objects, Box1 and Box2, and then laboriously worked through each of the data members for each object, in order to assign an initial value to it. This is unsatisfactory from several points of view. First of all, it would be easy to overlook initializing a data member, particularly in the case of a class which had many more data members than our Box class. Initializing the data members of several objects of a complex class could involve pages of assignment statements. The final constraint on this approach arises when we get to defining data members of a class that don't have the attribute public - we won't be able to access them from outside the class anyway. There has to be a better way, and of course there is - it's known as the class constructor.
A class constructor is a special function in a class that is called when a new object of the class is declared. It therefore provides the opportunity to initialize objects as they are created and to ensure that data members only contain valid values.
You have no leeway in naming a class constructor - it always has the same name as the class in which it is defined. The function Box(), for example, is a constructor for our Box class. It also has no return type. It's wrong to specify a return type for a constructor; you must not even write it as void. The primary function of a class constructor is to assign initial values to the data elements of the class, and no return type is necessary or, indeed, permitted.
Let's extend our Box class to incorporate a constructor.
// Ex6_03.cpp
// Using a constructor
#include <iostream>
using namespace std;
class Box // Class definition at global scope
{
public:
double length; // Length of a box in inches
double breadth; // Breadth of a box in inches
double height; // Height of a box in inches
// Constructor definition
Box(double lv, double bv, double hv)
{
cout << endl << "Constructor called.";
length = lv; // Set values of
breadth = bv; // data members
height = hv;
}
// Function to calculate the volume of a box
double Volume()
{
return length * breadth * height;
}
};
int main(void)
{
Box Box1(78.0,24.0,18.0); // Declare and initialize Box1
Box CigarBox(8.0,5.0,1.0); // Declare and initialize CigarBox
double volume = 0.0; // Store the volume of a box here
volume = Box1.Volume(); // Calculate volume of Box1
cout << endl
<< "Volume of Box1 = " << volume;
cout << endl
<< "Volume of CigarBox = "
<< CigarBox.Volume();
cout << endl;
return 0;
}
The constructor, Box(), has been written with three parameters of type double, corresponding to the initial values for the length, breadth and height members of a Box object. The first statement in the constructor outputs a message so that we can tell when it's been called. You wouldn't do this in production programs, but, since it's very helpful in showing when a constructor is called, it's often used when testing a program. We'll use it regularly for the purposes of illustration. The code in the body of the constructor is very simple. It just assigns the arguments passed to the corresponding data members. If necessary, we could also include checks that valid, non-negative arguments are supplied and, in a real context, you probably would want to do this, but our primary interest here is in seeing how the mechanism works.
Within main(), we declare the object Box1 with initializing values for the data members length, breadth, and height, in sequence. These are in parentheses following the object name. This uses the functional notation for initialization, which can also be applied to initializing ordinary variables of basic types. We also declare a second object of type Box, called CigarBox, which also has initializing values.
The volume of Box1 is calculated using the member function Volume() as in the previous example and is then displayed on the screen. We also display the value of the volume of CigarBox. The output from the example is:

The first two lines are output from the two calls of the constructor, Box(), once for each object declared. The constructor that we've supplied in the class definition is automatically called when a Box object is declared, so both Box objects are initialized with the initializing values appearing in the declaration. These are passed to the constructor as arguments, in the sequence that they are written in the declaration. As you can see, the volume of Box1 is the same as before and CigarBox has a volume looking suspiciously like the product of its dimensions, which is quite a relief.
Try modifying the last example by adding the declaration for Box2 that we had previously:
Box Box2; // Declare Box2 of type Box
Here, we've left Box2 without initializing values. When you rebuild this version of the program, you'll get the error message:
error C2512: 'Box': no appropriate default constructor available
This means that the compiler is looking for a default constructor for Box2, either one that needs no arguments, because none are specified in the constructor definition, or one whose arguments are all optional, because we haven't supplied any initializing values for the data members. Well, this statement was perfectly satisfactory in Ex6_02.cpp, so why doesn't it work now?
The answer is that the previous example used a default constructor that was supplied by the compiler, because we didn't supply one. Since in this example we did supply a constructor, the compiler assumed that we were taking care of everything and didn't supply the default. So, if you still want to use declarations for Box objects which aren't initialized, you have to include the default constructor yourself. What exactly does the default constructor look like? In the simplest case, it's just a constructor that accepts no arguments, it doesn't even need to do anything:
Box() // Default constructor
{} // Totally devoid of statements
Let's add our version of the default constructor to the last example, along with the declaration for Box2, plus the original assignments for the data members of Box2. We must enlarge the default constructor just enough to show that it is called. Here is the next version of the program:
// Ex6_04.cpp
// Supplying and using a default constructor
#include <iostream >
using namespace std;
class Box // Class definition at global scope
{
public:
double length; // Length of a box in inches
double breadth; // Breadth of a box in inches
double height; // Height of a box in inches
// Constructor definition
Box(double lv, double bv, double hv)
{
cout << endl << "Constructor called.";
length = lv; // Set values of
breadth = bv; // data members
height = hv;
}
// Default constructor definition
Box()
{ cout << endl << "Default constructor called."; }
// Function to calculate the volume of a box
double Volume()
{
return length * breadth * height;
}
};
int main(void)
{
Box Box1(78.0,24.0,18.0); // Declare and initialize Box1
Box Box2; // Declare Box2 - no initial values
Box CigarBox(8.0,5.0,1.0); // Declare and initialize CigarBox
double volume = 0.0; // Store the volume of a box here
volume = Box1.Volume(); // Calculate volume of Box1
cout << endl
<< "Volume of Box1 = " << volume;
Box2.height = Box1.height - 10; // Define Box2
Box2.length = Box1.length/2.0; // members in
Box2.breadth = 0.25*Box1.length; // terms of Box1
cout << endl
<< "Volume of Box2 = "
<< Box2.Volume();
cout << endl
<< "Volume of CigarBox = "
<< CigarBox.Volume();
cout << endl;
return 0;
}
Now that we have included our own version of the default constructor, there are no error messages from the compiler and everything works. The program produces this output:

All that our default constructor does is to display a message. Evidently, it was called when we declared the object Box2. We also get the correct value for the volumes of all three Box objects, so the rest of the program is working as it should.
One aspect of this example that you may have noticed is that we now know we can overload constructors just as we overloaded functions. We've just run an example with two constructors that differ only in their parameter list. One has three parameters of type double and the other has no parameters at all.
When we discussed functions in C++, we saw how we could specify default values for the parameters to a function in the function prototype. We can also do this for class member functions, including constructors. If we put the definition of the member function inside the class definition, we can put the default values for the parameters in the function header. If we only include the prototype of a function in the class definition, the default parameter value should go in the prototype.
If we decided that the default size for a Box object was a unit box with all sides of length 1, we could alter the class definition in the last example to this:
class Box // Class definition at global scope
{
public:
double length; // Length of a box in inches
double breadth; // Breadth of a box in inches
double height; // Height of a box in inches
// Constructor definition
Box(double lv = 1.0, double bv = 1.0, double hv = 1.0)
{
cout << endl << "Constructor called.";
length = lv; // Set values of
breadth = bv; // data members
height = hv;
}
// Default constructor definition
Box()
{ cout << endl << "Default constructor called."; }
// Function to calculate the volume of a box
double Volume()
{
return length * breadth * height;
}
};
If we make this change to the last example, what happens? We get another error message from the compiler, of course. We get these useful comments:
warning C4520: 'Box': multiple default constructors specified
error C2668: 'Box::Box': ambiguous call to overloaded function
This means that the compiler can't work out which of the two constructors to call - the one for which we have set default values for the parameters or the constructor that doesn't accept any parameters. This is because the declaration of Box2 requires a constructor without parameters, and either constructor can now be called in this case. The immediately obvious solution to this is to get rid of the constructor that accepts no parameters. This is actually beneficial. Without this constructor, any Box object that is declared without being explicitly initialized will automatically have its members initialized to 1.
We can demonstrate this with the following simplified example:
// Ex6_05.cpp
// Supplying default values for constructor arguments
#include <iostream>
using namespace std;
class Box // Class definition at global scope
{
public:
double length; // Length of a box in inches
double breadth; // Breadth of a box in inches
double height; // Height of a box in inches
// Constructor definition
Box(double lv=1.0, double bv=1.0, double hv=1.0)
{
cout << endl << "Constructor called.";
length = lv; // Set values of
breadth = bv; // data members
height = hv;
}
// Function to calculate the volume of a box
double Volume()
{
return length * breadth * height;
}
};
int main(void)
{
Box Box2; // Declare Box2 - no initial values
cout << endl
<< "Volume of Box2 = "
<< Box2.Volume();
cout << endl;
return 0;
}
We only declare a single uninitialized Box variable, Box2, because that's all we need for demonstration purposes. This version of the program produces the following output:

This shows that the constructor with default parameter values is doing its job of setting the values of objects that have no initializing values specified.
You shouldn't assume from the above example that this is the only, or even the recommended, way of implementing the default constructor. There will be many occasions where you won't want to assign default values in this way, in which case you'll need to write a separate default constructor. There will even be times when you don't want to have a default constructor operating at all, even though you have defined another constructor. This would ensure that all declared objects of a class must have initializing values explicitly specified in their declaration.
Previously, we initialized the members of an object in the class constructor using explicit assignment. We could also have used a different technique, using what is called an initialization list. We can demonstrate this with an alternative version of the constructor for the class Box:
// Constructor definition using an initialization list
Box(double lv=1.0, double bv=1.0, double hv=1.0): length(lv),
breadth(bv),
height(hv)
{
cout << endl << "Constructor called.";
}
Now the values of the data members are not set in assignment statements in the body of the constructor. As in a declaration, they are specified as initializing values using functional notation and appear in the initializing list as part of the function header. The member length is initialized by the value of lv, for example. This can be rather more efficient than using assignments as we did in the previous version. If you substitute this version of the constructor in the previous example, you will see that it works just as well.
Note that the initializing list for the constructor is separated from the parameter list by a colon and that each of the initializers is separated by a comma. This technique for initializing parameters in a constructor is important, because, as we shall see later, it's the only way of setting values for certain types of data members of an object.