Constructors in C++
A constructor is a special member function that is automatically called when an object of a class is created. It initializes the object’s data members.
What is a Constructor?
A constructor has the same name as the class and no return type (not even void). Its primary purpose is to initialize objects.
Key Characteristics:
- Same name as the class
- No return type
- Automatically called when object is created
- Can be overloaded
- Cannot be inherited
Types of Constructors
- Default Constructor
- Parameterized Constructor
- Copy Constructor
- Move Constructor (C++11)
1. Default Constructor
A constructor with no parameters:
#include <iostream>
using namespace std;
class Student {
private:
string name;
int age;
public:
// Default constructor
Student() {
name = "Unknown";
age = 0;
cout << "Default constructor called" << endl;
}
void display() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
Student s1; // Default constructor is called
s1.display();
return 0;
}Output:
Default constructor called
Name: Unknown, Age: 02. Parameterized Constructor
A constructor that accepts parameters:
#include <iostream>
#include <string>
using namespace std;
class Car {
private:
string brand;
string model;
int year;
public:
// Parameterized constructor
Car(string b, string m, int y) {
brand = b;
model = m;
year = y;
cout << "Parameterized constructor called" << endl;
}
void display() {
cout << year << " " << brand << " " << model << endl;
}
};
int main() {
Car car1("Toyota", "Camry", 2023);
car1.display();
Car car2("Honda", "Civic", 2024);
car2.display();
return 0;
}Output:
Parameterized constructor called
2023 Toyota Camry
Parameterized constructor called
2024 Honda CivicConstructor Overloading
You can have multiple constructors with different parameters:
#include <iostream>
using namespace std;
class Rectangle {
private:
double length;
double width;
public:
// Default constructor
Rectangle() {
length = 1.0;
width = 1.0;
}
// Parameterized constructor with one parameter (square)
Rectangle(double side) {
length = side;
width = side;
}
// Parameterized constructor with two parameters
Rectangle(double l, double w) {
length = l;
width = w;
}
double getArea() {
return length * width;
}
void display() {
cout << "Length: " << length << ", Width: " << width;
cout << ", Area: " << getArea() << endl;
}
};
int main() {
Rectangle r1; // Calls default constructor
Rectangle r2(5); // Calls single parameter constructor
Rectangle r3(4, 6); // Calls two parameter constructor
r1.display();
r2.display();
r3.display();
return 0;
}Output:
Length: 1, Width: 1, Area: 1
Length: 5, Width: 5, Area: 25
Length: 4, Width: 6, Area: 24Member Initializer List
A more efficient way to initialize members:
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int rollNumber;
double gpa;
public:
// Using member initializer list
Student(string n, int r, double g) : name(n), rollNumber(r), gpa(g) {
cout << "Student created using initializer list" << endl;
}
void display() {
cout << "Name: " << name << endl;
cout << "Roll: " << rollNumber << endl;
cout << "GPA: " << gpa << endl;
}
};
int main() {
Student s1("Alice", 101, 3.9);
s1.display();
return 0;
}Output:
Student created using initializer list
Name: Alice
Roll: 101
GPA: 3.93. Copy Constructor
Creates a new object as a copy of an existing object:
#include <iostream>
using namespace std;
class Point {
private:
int x, y;
public:
// Parameterized constructor
Point(int xVal, int yVal) : x(xVal), y(yVal) {
cout << "Parameterized constructor called" << endl;
}
// Copy constructor
Point(const Point& p) {
x = p.x;
y = p.y;
cout << "Copy constructor called" << endl;
}
void display() {
cout << "Point(" << x << ", " << y << ")" << endl;
}
};
int main() {
Point p1(10, 20);
p1.display();
Point p2 = p1; // Copy constructor is called
p2.display();
Point p3(p1); // Another way to call copy constructor
p3.display();
return 0;
}Output:
Parameterized constructor called
Point(10, 20)
Copy constructor called
Point(10, 20)
Copy constructor called
Point(10, 20)Deep Copy vs Shallow Copy
Shallow Copy (Default behavior)
class Array {
private:
int* data;
int size;
public:
Array(int s) : size(s) {
data = new int[size];
}
// If no copy constructor is defined,
// shallow copy happens (both objects point to same memory)
};Deep Copy (Proper way)
#include <iostream>
using namespace std;
class Array {
private:
int* data;
int size;
public:
// Constructor
Array(int s) : size(s) {
data = new int[size];
for (int i = 0; i < size; i++) {
data[i] = i;
}
}
// Deep copy constructor
Array(const Array& other) : size(other.size) {
data = new int[size]; // Allocate new memory
for (int i = 0; i < size; i++) {
data[i] = other.data[i]; // Copy values
}
cout << "Deep copy created" << endl;
}
// Destructor
~Array() {
delete[] data;
}
void display() {
cout << "Array: ";
for (int i = 0; i < size; i++) {
cout << data[i] << " ";
}
cout << endl;
}
};
int main() {
Array arr1(5);
arr1.display();
Array arr2 = arr1; // Deep copy
arr2.display();
return 0;
}Output:
Array: 0 1 2 3 4
Deep copy created
Array: 0 1 2 3 4Default Arguments in Constructors
#include <iostream>
using namespace std;
class Book {
private:
string title;
string author;
int pages;
public:
// Constructor with default arguments
Book(string t = "Unknown", string a = "Unknown", int p = 0)
: title(t), author(a), pages(p) {}
void display() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
cout << "Pages: " << pages << endl << endl;
}
};
int main() {
Book b1; // All defaults
Book b2("1984"); // Partial defaults
Book b3("Animal Farm", "George Orwell"); // Partial defaults
Book b4("The Hobbit", "J.R.R. Tolkien", 310); // No defaults
b1.display();
b2.display();
b3.display();
b4.display();
return 0;
}Output:
Title: Unknown
Author: Unknown
Pages: 0
Title: 1984
Author: Unknown
Pages: 0
Title: Animal Farm
Author: George Orwell
Pages: 0
Title: The Hobbit
Author: J.R.R. Tolkien
Pages: 310Explicit Constructor
Prevents implicit type conversions:
#include <iostream>
using namespace std;
class Integer {
private:
int value;
public:
// Explicit constructor
explicit Integer(int v) : value(v) {}
void display() {
cout << "Value: " << value << endl;
}
};
int main() {
Integer i1(10); // OK
// Integer i2 = 20; // Error: implicit conversion not allowed
i1.display();
return 0;
}Delegating Constructors (C++11)
One constructor can call another:
#include <iostream>
using namespace std;
class Box {
private:
double length, width, height;
public:
// Main constructor
Box(double l, double w, double h) : length(l), width(w), height(h) {
cout << "Main constructor called" << endl;
}
// Delegating constructors
Box() : Box(1, 1, 1) {
cout << "Default constructor delegates to main" << endl;
}
Box(double side) : Box(side, side, side) {
cout << "Cube constructor delegates to main" << endl;
}
double getVolume() {
return length * width * height;
}
};
int main() {
Box b1;
cout << "Volume: " << b1.getVolume() << endl << endl;
Box b2(5);
cout << "Volume: " << b2.getVolume() << endl;
return 0;
}Output:
Main constructor called
Default constructor delegates to main
Volume: 1
Main constructor called
Cube constructor delegates to main
Volume: 125Constructor Best Practices
- Always initialize all members: Uninitialized data can cause bugs
- Use initializer lists: More efficient than assignment in body
- Make single-argument constructors explicit: Prevents unwanted conversions
- Provide default constructor when needed
- Implement copy constructor for classes with dynamic memory
- Use const references for copy constructor parameters
Common Mistakes
1. Missing Initialization
// Wrong
class MyClass {
int* ptr;
public:
MyClass() {} // ptr is uninitialized!
};
// Correct
class MyClass {
int* ptr;
public:
MyClass() : ptr(nullptr) {}
};2. Calling Constructor Explicitly
// Wrong
MyClass obj;
obj.MyClass(); // Error: Can't call constructor like this
// Correct
MyClass obj; // Constructor is called automaticallyPractice Exercises
-
Bank Account: Create a class with constructor to initialize account number, name, and balance
-
Date Class: Implement a Date class with constructors for different date formats
-
Matrix: Create a Matrix class with constructors for different initializations
-
String Class: Implement your own String class with proper copy constructor
-
Complex Number: Create a Complex class with multiple constructors for different representations
Constructors are essential for proper object initialization in C++!