What is a Constructor in C++?

What is a Constructor in C++?

In C++ programming, constructors are special functions inside a class. They run automatically when you create an object. The main job of a constructor is to set up or initialize the object with starting values. Constructors are an important part of object-oriented programming.

Before diving into constructors in C++, it’s essential to have a strong understanding of the fundamentals of the language. With a firm grasp of these prerequisites, constructors, which can seem like an abstract concept, become easier to grasp, with concepts like language semantics and basics, object-oriented programming, classes and objects, functions in C++, and exception handling in C++. In this blog, we are going to walk you through the different types of constructors and their working. So let’s get started!

Table of Contents

Introduction to Constructors in C++

A constructor in C++ is a special member function responsible for initializing the data members of an object when the same is created. 

  • A constructor’s nomenclature closely resembles the class. It has the same name as the class with no return type.
  • Constructors are invoked automatically when an object is created and can take arguments to initialize the object’s data members.
  • It is usually declared in public scope. However, it can be declared in private scope, as well.

For instance, consider a class called Car with make, model, and year as its data members. We can create a constructor for the Car class that takes arguments for each of these data members and initializes them when a Car object is created.

Here’s a basic C++ constructor example:

#include <iostream>
class MyClass {
public:
    MyClass() { std::cout << "Constructor called!" << std::endl; }
};
int main() {
    MyClass obj;
    return 0;
}

The above code is used to demonstrate a default constructor in C++. It automatically runs when an object of the class is created, which prints a message

“Constructor called”.

Types of Constructors in C++

As mentioned above, constructors are special member functions responsible for initializing the objects of a class. Understanding the different types of constructors is essential for developing robust and efficient C++ programs. There are three types of constructors in C++, namely default, parameterized, and copy constructors.

1. Default Constructor

A default constructor takes no arguments. Thus, it is called, by default, when an object is created without any arguments. The default constructor initializes the data members of an object to their default values.

Example Usage:

#include <iostream>
using namespace std;

class Car {
public:
Car() {
cout << "Default constructor called: Car object created!" << endl;
}
};

int main() {
Car myCar;
return 0;
}

Output

Default Constructor called: Car object created!

Explanation

The above code defines a Car class by using a default constructor. It then prints the message when the Car object is created.

Get 100% Hike!

Master Most in Demand Skills Now!

2. Parameterized Constructor

A parameterized constructor takes one or more arguments. It is used to initialize the data members of an object, with specific values that the user provides.

Example Usage

#include <iostream>
using namespace std;

class Car {
string brand;
public:
Car(string b) {
brand = b;
cout << "Parameterized constructor called: Brand = " << brand << endl;
}
};

int main() {
Car car1("Toyota");
Car car2("Ford");
return 0;
}

Output

Parameterized constructor called: Brand = Toyota
Parameterized constructor called: Brand = Ford

Explanation

In the above code, the Car class is defined with a parameterized constructor. It initializes the brand of the car and then prints it when each Car object is created.

3. Copy Constructor

A C++ copy constructor creates an object by initializing it with an existing object of the same class. Simply put, it creates a new object with the same values as an existing object.

Example Usage

#include <iostream>
using namespace std;

class Car {
string brand;
public:
Car(string b) {
brand = b;
}

// Copy constructor
Car(const Car &obj) {
brand = obj.brand;
cout << "Copy constructor called: Copied brand = " << brand << endl;
}
};

int main() {
Car car1("BMW");
Car car2 = car1; // Calls copy constructor
return 0;
}

Output

Copy Constructor called: Copied brand = BMW

Explanation

The above code is used to demonstrate a copy constructor. It creates a new Car object by copying the brand from an existing object. After that, it prints the confirmation message.

4. Move Constructor

Move Constructor is a recent addition to the family of constructors in C++. It helps one object to take over the resources of another temporary object, instead of copying the objects. This helps to make the process faster and avoids unwanted duplication. It uses the std::move() function to transfer ownership. It is automatically called when a temporary object is given to a function or when it is returned from one. This helps the program to reuse its resources instead of copying them.

Syntax for Move Constructor

className (className&& obj) {
// body of the constructor
}

Example Usage

#include <iostream>
#include <vector>
using namespace std;

class MyClass {
private:
int b;

public:
// Constructor
MyClass(int &&a) : b(move(a)) {
cout << "Move constructor called!" << endl;
}

void display() {
cout << b <<endl;
}
};

int main() {
int a = 4;
MyClass obj1(move(a)); // Move constructor is called

obj1.display();
return 0;
}

Output

Move constructor called!
4

Explanation

In the above code, the MyClass constructor is used to take an rvalue reference (int &&a). It then moves the value of a into the private member b by using the std::move function. After that, the main function creates an integer a, and then it is moved into obj1 by calling the move constructor.

Constructor Overloading

C++ Constructor overloading is one of the handiest features of C++. It empowers developers to define multiple constructors for each of the classes that they design. This means that classes can offer more flexibility when creating objects, thus providing options like varying numbers or types of initial inputs that are tailored specifically to the needs of each program.

For the purpose of illustration, let’s say that we’re working on building a ‘Rectangle‘ class, representing the shape of rectangles through their length and width measurements. You could use this feature by setting up two distinct constructors—one without any initial inputs, setting both length and width at 1, and another designed for custom lengths and widths through specified input values. The example code for the illustration is given below:

Example Usage

#include <iostream>
using namespace std;

class Rectangle {
int length;
int width;

public:
// Default constructor: sets length and width to 1
Rectangle() {
length = 1;
width = 1;
cout << "Default constructor called: Length = " << length << ", Width = " << width << endl;
}

// Parameterized constructor: sets custom length and width
Rectangle(int l, int w) {
length = l;
width = w;
cout << "Parameterized constructor called: Length = " << length << ", Width = " << width << endl;
}

int area() {
return length * width;
}
};

int main() {
Rectangle rect1; // Uses default constructor
Rectangle rect2(5, 3); // Uses parameterized constructor

cout << "Area of rect1: " << rect1.area() << endl;
cout << "Area of rect2: " << rect2.area() << endl;

return 0;
}

Output

Default constructor called: Length: 1, Width = 1
Parameterized constructor called: Length: 5, Width = 3
Area of rect1: 1
Area of rect2: 15

Explanation

The above code clearly shows constructor overloading. The Rectangle class can only be initialized with either default values or with specific values of length and width.

In addition to overloading constructors with different parameters, we can overload constructors with default parameter values, as well. For example:

#include <iostream>
using namespace std;

class Circle {
private:
double radius;
double x, y;

public:
// Constructor with default values for all parameters
Circle(double r = 1.0, double xCoord = 0.0, double yCoord = 0.0) {
radius = r;
x = xCoord;
y = yCoord;
cout << "Circle created with Radius = " << radius
<< ", Center = (" << x << ", " << y << ")" << endl;
}
};

int main() {
Circle c1; // Uses default values (1.0, 0.0, 0.0)
Circle c2(5.0); // Sets radius to 5.0, center remains (0.0, 0.0)
Circle c3(3.5, 2.0, 4.0); // Sets radius and custom center

return 0;
}

Output

Circle created with Radius = 1, Center = (0, 0)
Circle created with Radius = 5, Center = (0, 0)
Circle created with Radius = 3.5, Center = (2, 4)

Explanation

The above code is used to demonstrate constructor overloading with the help of default parameters in C++. This helps to create Circle objects with various levels of customization for the radius and center coordinates.

Circle c1; // Uses C++ default constructor with no parameters
Circle c2(2.5); // Uses constructor with single double parameter
Circle c3(3.0, 1.0, 2.0); // Uses constructor with three double parameters
Circle c4(4.0, 3.0); // Uses constructor with default y-coordinate value

Benefits of Using Constructors

A constructor is one of the vital features of OOPS-based programming languages. It provides several benefits to the programmers and developers with respect to code organization, memory management, and initialization. 

Below mentioned are some of the key benefits of using constructors while coding:

  • Initialization: Constructors provide a way to initialize the data members of an object when created. A constructor ensures that the object is valid from the beginning and eliminates the need for separate initialization functions.
  • Code organization: Constructors help organize the code by grouping related operations. By defining constructors within a class, the programmer can ensure that the initialization code is located at one location, making it easier to maintain and modify.
  • Encapsulation: Constructors can enforce encapsulation by setting the data members of the class to private and providing public constructors to create and initialize the object. It helps in protecting the data contained within the object from external manipulation and ensures that the object is always in a valid state.
  • Default constructors: When no constructor is defined, the compiler generates a default constructor that initializes all data members to their default values. Constructors can be helpful when working with arrays of objects or creating objects without providing specific initialization values.
  • Inheritance: Constructors can be inherited from base classes and overridden in derived classes, allowing for customization of initialization behavior. It helps maintain consistency and flexibility across related classes.
  • Memory management: Constructors can manage memory allocation and deallocation for dynamically allocated objects. They ensure that memory is properly allocated and deallocated, preventing memory leaks and other issues.

Conclusion

Constructors offer several benefits, including ensuring that an object is properly initialized before it can be used, improving code readability and maintainability, and allowing for more flexibility in object creation through constructor overloading. Understanding the various types of constructors available and how they can be used helps developers create more robust and effective C++ programs.

Incorporating constructors into your programming knowledge can be a valuable asset for creating efficient, readable, and maintainable C++ code. With the ability to initialize data members and provide additional flexibility in object creation, constructors can significantly enhance the functionality and usability of your C++ programs. By utilizing the benefits of constructors, developers can streamline their code and focus on creating innovative and dynamic software solutions.

About the Author

Senior Consultant Analytics & Data Science, Eli Lilly and Company

Sahil Mattoo, a Senior Software Engineer at Eli Lilly and Company, is an accomplished professional with 14 years of experience in languages such as Java, Python, and JavaScript. Sahil has a strong foundation in system architecture, database management, and API integration.