A constructor is a special type of member function that is called automatically when an object is created.
In C++, a constructor has the same name as that of the class, and it does not have a return type. For example,
class Wall {
public:
// create a constructor
Wall() {
// code
}
};
Here, the function Wall()
is a constructor of the class Wall
. Notice that the constructor
- has the same name as the class,
- does not have a return type, and
- is
public
C++ Default Constructor
A constructor with no parameters is known as a default constructor. For example,
// C++ program to demonstrate the use of default constructor
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double length;
public:
// default constructor to initialize variable
Wall():length{5.5} {
cout << "Creating a wall." << endl;
cout << "Length = " << length << endl;
}
};
int main() {
Wall wall1;
return 0;
}
Output
Creating a Wall Length = 5.5
Here, when the wall1 object is created, the Wall()
constructor is called. length{5.5}
is invoked when the constructor is called, and sets the length variable of object to 5.5
.
Note: If we have not defined a constructor in our class, then the C++ compiler will automatically create a default constructor with an empty code and no parameters.
C++ Parameterized Constructor
In C++, a constructor with parameters is known as a parameterized constructor. This is the preferred method to initialize member data. For example,
// C++ program to calculate the area of a wall
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double length;
double height;
public:
// parameterized constructor to initialize variables
Wall(double len, double hgt):length{len}, height{hgt} {
}
double calculateArea() {
return length * height;
}
};
int main() {
// create object and initialize data members
Wall wall1(10.5, 8.6);
Wall wall2(8.5, 6.3);
cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
cout << "Area of Wall 2: " << wall2.calculateArea();
return 0;
}
Output
Area of Wall 1: 90.3 Area of Wall 2: 53.55
Here, we have created a parameterized constructor Wall()
that has two parameters: double len
and double hgt
. The values contained in these parameters are used to initialize the member variables length and height.
length{len}, height{hgt}
is the initialization list.
length{len}
initializes the member variable length with the value of the parameter lenheight{hgt}
initializes the member variable height with the value of the parameter hgt.
When we create an object of the Wall
class, we pass the values for the member variables as arguments. The code for this is:
Wall wall1(10.5, 8.6);
Wall wall2(8.5, 6.3);
With the member variables thus initialized, we can now calculate the area of the wall with the calculateArea()
function.
Note: A constructor is primarily used to initialize objects. They are also used to run a default code when an object is created.
C++ Copy Constructor
The copy constructor in C++ is used to copy data from one object to another. For example,
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double length;
double height;
public:
// initialize variables with parameterized constructor
Wall(double len, double hgt): length{len}, height{hgt} {
}
// copy constructor with a Wall object as parameter
// copies data of the obj parameter
Wall(const Wall& obj):length{obj.length}, height{obj.height} {
}
double calculateArea() {
return length * height;
}
};
int main() {
// create an object of Wall class
Wall wall1(10.5, 8.6);
// copy contents of wall1 to wall2
Wall wall2 = wall1;
// print areas of wall1 and wall2
cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
cout << "Area of Wall 2: " << wall2.calculateArea();
return 0;
}
Output
Area of Wall 1: 90.3 Area of Wall 2: 90.3
In this program, we have used a copy constructor to copy the contents of one object of the Wall
class to another. The code of the copy constructor is:
Wall(const Wall& obj):length{obj.length}, height{obj.height} {
}
Notice that the parameter of this constructor has the address of an object of the Wall
class.
We then assign the values of the variables of the obj object to the corresponding variables of the object, calling the copy constructor. This is how the contents of the object are copied.
In main()
, we then create two objects wall1 and wall2 and then copy the contents of wall1 to wall2:
// copy contents of wall1 to wall2
Wall wall2 = wall1;
Here, the wall2 object calls its copy constructor by passing the reference of the wall1 object as its argument.
C++ Default Copy Constructor
If we don't define a constructor in our class, then the C++ compiler will automatically create a default copy constructor that does memberwise copy assignment. It suffices in most cases. For example,
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double length;
double height;
public:
// initialize variables with parameterized constructor
Wall(double len, double hgt): length{len}, height{hgt} {
}
double calculateArea() {
return length * height;
}
};
int main() {
// create an object of Wall class
Wall wall1(10.5, 8.6);
// copy contents of wall1 to wall2 by default copy constructor
Wall wall2 = wall1;
// print areas of wall1 and wall2
cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
cout << "Area of Wall 2: " << wall2.calculateArea();
return 0;
}
Output
Area of Wall 1: 90.3 Area of Wall 2: 90.3
In this program, we have not defined a copy constructor. The compiler used the default copy constructor to copy the contents of one object of the Wall
class to another.
Destructor
A destructor is a special type of member function that is called automatically when an object is destroyed.
In C++, a destructor has the same name as that of the class, and it does not have a return type. ~
precedes the identifier to indicate destructor. For example,
class Wall {
public:
// create a destructor
~Wall() {
// code
}
};
Here, the function ~Wall()
is a destructor of the class Wall
.
Note: If we don't define a destructor in our class, then the C++ compiler will automatically create a default destructor with an empty body. It suffices in most cases.
However, if our class involves resource handling like dynamic memory allocation, we have to define a destructor and deallocate the resources in the destructor body.
Dynamic Memory Allocation in Class
When our class has pointer members, the default copy constructor just assigns the value of member pointers of one object to the member pointers of another object, rather than allocating different memory addresses and copying the value pointed by the member pointers.
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double* length;
double* height;
public:
// initialize variables with parameterized constructor
Wall(double len, double hgt): length{new double{len}}, height{new double{hgt}} {
}
void setLength(double len) {
*length = len;
}
double calculateArea() {
return *length * *height;
}
};
int main() {
// create an object of Wall class
Wall wall1(10.5, 8.6);
// copy contents of wall1 to wall2
Wall wall2 = wall1;
// change the length of wall2
wall2.setLength(11.5);
// print areas of wall1 and wall2
cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
cout << "Area of Wall 2: " << wall2.calculateArea();
return 0;
}
Output
Area of Wall 1: 98.9 Area of Wall 2: 98.9
In this program, we have used the default copy constructor to copy the contents of wall1
to wall2
.
The default copy constructor assigns the values of the variables of wall1
to the corresponding variables of wall2
, calling the copy constructor.
When we change the length of wall2
, the length of wall1
is also changed. This is because length pointer of both wall1
and wall2
point to the same memory address.
To allocate new memory address for the variable and copy the data, we have to declare a copy constructor. Moreover, we have to deallocate the memory using destructor.
#include <iostream>
using namespace std;
// declare a class
class Wall {
private:
double* length;
double* height;
public:
// initialize variables with parameterized constructor
Wall(double len = 1.0, double hgt = 1.0): length{new double{len}}, height{new double{hgt}} {
}
// copy constructor with a Wall object as parameter
// copies data of the obj parameter
Wall(const Wall& obj):length{new double{*(obj.length)}}, height{new double{*(obj.height)}} {
}
void setLength(double len) {
*length = len;
}
double calculateArea() {
return *length * *height;
}
// destructor to deallocate memory
~Wall() {
delete length;
delete height;
}
};
int main() {
// create an object of Wall class
Wall wall1(10.5, 8.6);
// copy contents of wall1 to wall2 by default copy constructor
Wall wall2 = wall1;
// change the length of wall2
wall2.setLength(11.5);
// print areas of wall1 and wall2
cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
cout << "Area of Wall 2: " << wall2.calculateArea();
return 0;
}
Output
Area of Wall 1: 90.3 Area of Wall 2: 98.9
Here,
Wall(const Wall& obj):length{new double{*(obj.length)}}, height{new double{*(obj.height)}} {
}
is the copy constructor. It takes an object obj of Wall
as argument by const
reference.
length{new double{*(obj.length)}}, height{new double{*(obj.height)}} is the initialization list that copies the data to new memory locations and initializes the length and height pointers accordingly.
*(obj.length)
is the value pointed bylength
pointer member of the argument object objnew double{*(obj.length)}
dynamically allocates memory fordouble
datatype with the value*(obj.length)
and returns the memory addresslength{new double {*obj.length)}}
initializes thelength
variable of the new object with the new memory address.
Similarly,
height{new double{*(obj.height)}}
initializes the height
pointer member of the new object.
Also Read