This is a special type of member function called a constructor. A constructor for a class is responsible for initializing the member variables of new objects of that type. Any time we make a Point, the constructor will make sure m_x and m_y are set.
A constructor always has the same name as the class and it lacks a return type - the return type is implied to be the class type. When you use a Point constructor, a new Point is always created and it is what gets automatically returned:
// A Point constructor
Point(double x, double y) {
// A new point is created when we enter the constructor
m_x = x;
m_y = y;
// implicit return of the new point
}
There is a subtle difference between the two. The first says βCreate a Point with 3 and 4. Copy that point into p1.β The second says βCreate Point p1 with 3 and 4.β and thus skips making an anonymous (nameless) Point that then gets copied into p1 and then throws away the anonymous Point. Either syntax will produce the same results, but you should recognize that Point(3, 4) creates an anonymous point.
We can overload the constructor of a class in the same way we can overload other functions. Say we want to be able to easily create points at (0, 0) without saying Point p1(0, 0);. We could write a no argument constructor Point() that automatically set x and y to 0. Or if we wanted (for some unknown reason) to be able to easily make points with the same x and y value we might write Point(double sharedCoordinate);:
Point p1(3, 4); // Point at (3, 4)
Point p2; // Point at (0, 0)
Point p3(5); // Point at (5, 5)
In this case, the compiler will automatically pick the constructor that best matches the arguments we give it. If we give it two arguments, it will use the two-argument constructor. If we give it one argument, it will use the one-argument constructor.
The no-argument constructor is a special case. To call it we could say Point p2 = Point();. But to write the short version, we have to leave off the parentheses: Point p2;. This somewhat annoying special case is a quirk of the syntax of C++. Point p2(); looks like it defines a function called p2 that returns a Point.
Remember that declaring a variable of a class automatically calls the no argument constructor unless we use (...) after the variable name to call a different constructor. Because it is called automatically when we donβt use (...), it is also known as the default constructor.
If you fail to define any constructors, a default one is automatically provided by the compiler, but it doesnβt actually initialize any data - you should always define constructors for every class you write.
But if we know there are default values that should always be applied, we might want to specify those directly in the class itself. Try running this Codelens sample and notice that the member variables are both set to 0 automatically at the start of each constructor. This is because the variables themselves are given default values of 0 on lines 15 and 16:
Assigning default values at the class level can prevent having to do so in multiple constructors. Say we want to provide many different constructors for a Time class. We could either write this:
class Time {
public:
// Fully specified time
Time(int hours, int minutes, int seconds) {
m_hours = hours;
m_minutes = minutes;
m_seconds = seconds;
}
// Assume seconds is 0
Time(int hours, int minutes) {
m_hours = hours;
m_minutes = minutes;
}
// Assume minutes and seconds are 0
Time(int hours) {
m_hours = hours;
}
// Default constructor
Time() {}
private:
int m_hours = 0;
int m_minutes = 0;
int m_seconds = 0;
};
Note16.6.2.
Every constructor should make sure that every member variable has some reasonable starting value. If the constructor does not take a value to use for a given variable, a default value should be assigned either in the constructor or where the member variable is declared .
As with structs, we can copy one object into another using the assignment operator =. Doing so results in two distinct objects that happen to have the same data:
There are ways to customize what the assignment operator does with objects. Those techniques are important for objects that are in charge of managing resources. But for the simple objects we are working with for now, the default behavior of the assignment operator works just fine.
Letβs write two constructors for Student. One with no arguments and one with arguments. Put the necessary blocks of code in the correct order with the no-argument constructor first.