Constructors
Contents
2.2. Constructors#
In the previous section, we learned about classes and how to define them. We saw private and public members, and the need for getter and setter functions to access and modify private members. In this section, we will learn about constructors, which are special member functions of a class that are called when an object of the class is instantiated. Constructors are used to initialize the members of a class when an object is created.
2.2.1. Default Constructor#
Recall the example of the Student
class, we used in the previous section.
Code in Student.h
#include <string>
using namespace std;
class Student {
private:
string name;
int ID;
public:
void print();
void setName(string name);
string getName();
};
Code in Student.cpp
#include <iostream>
#include "Student.h"
using namespace std;
void Student::print() {
cout << "Name: " << name << endl << "ID: " << ID << endl;
}
void Student::setName(string n) {
name = n;
}
string Student::getName() {
return name;
}
Code in main.cpp
1#include <iostream>
2#include "Student.h"
3using namespace std;
4
5int main(void) {
6 Student x;
7
8 x.setName("Cindy");
9 cout << x.getName() << endl;
10
11 x.print(); // ID is not initialized
12 return 0;
13}
Problem! As we create the object x
, the value of name
and ID
are uninitialized. It is a good practice to initialize value of variables as we declare them to avoid having undefined behavior resulting from uninitialized variables. For example, in line 11, the output of the program is undefined as the value of ID
is not initialized.
Solution! To initialize the members of a class when an object is created, we can use a constructor. A constructor is a special member function of a class that is given by default when a class is defined. It is called automatically when an object is created. By default, the constructor is an empty function that does nothing. This is called a default constructor. We can define our own constructor to initialize the members of a class when an object is created.
The constructor has
the same name as the class
no return type (not even
void
)called when an object is created, but never called explicitly
must be a public member
Let’s define a constructor for the Student
class to initialize the name
and ID
members.
Code in Student.h
1#include <string>
2using namespace std;
3
4class Student {
5 private:
6 string name;
7 int ID;
8
9 public:
10 Student(); // Constructor
11 void print();
12 void setName(string name);
13 string getName();
14};
In Student.h
file, in line 10, we add the constructor declaration to the Student
class. The constructor is a function with the same name as the class and no return type.
Code in Student.cpp
1#include <iostream>
2#include "Student.h"
3using namespace std;
4
5Student::Student() {
6 ID = 0;
7 name = "no name";
8}
9
10void Student::print() {
11 cout << "Name: " << name << endl << "ID: " << ID << endl;
12}
13
14void Student::setName(string n) {
15 name = n;
16}
17
18string Student::getName() {
19 return name;
20}
In Student.cpp
file, we add the constructor implementation for the Student
class. No return type is specified for the constructor. We are setting the value of ID
to 0
and name
to "no name"
in the default constructor.
Code in main.cpp
1#include <iostream>
2#include "Student.h"
3using namespace std;
4
5int main(void) {
6 Student x; // Constructor is called
7
8 x.print();
9 return 0;
10}
Output
Name: no name ID: 0
In main.cpp
file, we create an object x
of the Student
class. The constructor is called automatically when the object is created. The value of name
and ID
are initialized to "no name"
and 0
, respectively. The output of the program is now defined.
Student y[10];
creates an array of 10 Student
objects. The constructor is called for each object in the array, i.e., the constructor is called 10 times.
Student *z;
creates a pointer z
to a Student
object. The pointer is not initialized and has a garbage address. The constructor is not called as no object is created. The constructor is called when an object is created, not when a pointer is created.
2.2.2. Other Constructors#
As we have seen, the default constructor has no parameters passed to it. What if we want to initialize the members of a class with some values when an object is created? We can define our own constructor with parameters. These are called parameterized constructors.
Code in Student.h
1#include <string>
2using namespace std;
3
4class Student {
5 private:
6 string name;
7 int ID;
8
9 public:
10 Student(); // Default constructor
11 Student(int id); // 1st constructor
12 Student(int id, string n); // 2nd constructor
13 void print();
14 void setName(string name);
15 string getName();
16};
In Student.h
file, we add two more constructors to the Student
class. The first constructor in line 7 takes an integer parameter id
and initializes the ID
member with the value of id
, and sets the name
member to "no name"
.
The second constructor in line 8 takes an integer parameter id
and a string parameter n
and initializes the ID
and name
members with the values of id
and n
, respectively.
Code in Student.cpp
1#include "Student.h"
2#include <iostream>
3using namespace std;
4
5Student::Student() {
6 ID = 0;
7 name = "no name";
8}
9
10Student::Student(int id) {
11 ID = id;
12 name = "no name";
13}
14
15Student::Student(int id, string n) {
16 ID = id;
17 name = n;
18}
19
20void Student::print() {
21 cout << "Name: " << name << endl << "ID: " << ID << endl;
22}
23
24void Student::setName(string n) {
25 name = n;
26}
27
28string Student::getName() {
29 return name;
30}
In Student.cpp
file, we add the implementation for the two new constructors. The first constructor in lines 10-13 initializes the ID
member with the value of id
and sets the name
member to "no name"
.
The second constructor in lines 15-18 initializes the ID
and name
members with the values of id
and n
, respectively.
Code in main.cpp
1#include <iostream>
2#include "Student.h"
3using namespace std;
4
5int main(void) {
6 Student x; // Default constructor is called
7 Student y(20207); // 1st constructor is called
8 Student z(20207, "Osiris"); // 2nd constructor is called
9 cout << "Student x" << endl;
10 x.print();
11 cout << "Student y" << endl;
12 y.print();
13 cout << "Student z" << endl;
14 z.print();
15 return 0;
16}
Output
Student x: Name: no name ID: 0 Student y: Name: no name ID: 20207 Student z: Name: Osiris ID: 20207
In the main function, we create three objects x
, y
, and z
of the Student
class. The default constructor is called for object x
, the first constructor is called for object y
, and the second constructor is called for object z
. The value of name
and ID
members are initialized accordingly as shown in the output.
How is it possible to have multiple constructors with same name but different number of parameters?
The constructors are distinguished by the number of parameters passed to them. The compiler determines which constructor to call based on the number of parameters passed to it. Defining multiple constructors with the same name but different number of parameters is called function overloading. This is used for other functions as well, not just constructors.
Important!
If the default constructor is not defined, the compiler will provide one.
However, if any constructor is defined, for example, the first constructor in the example above, the compiler will not provide the default constructor. In that case, for example, Student x;
will result in a compilation error as the default constructor Student::Student()
is not defined.