What is a Parameterized Constructor?
A parameterized constructor is a constructor that takes one or more parameters when an object is created. It allows you to provide specific values to initialize the object’s data members at the time of creation.
Why Use Parameterized Constructors?
Parameterized constructors are useful for:
- Initializing objects with specific values at creation time
- Avoiding the need to call setter methods after object creation
- Ensuring objects are created in a valid state with all required data
- Making code more concise and readable
Basic Syntax
class ClassName {
private:
// Data members
public:
// Parameterized constructor
ClassName(parameter1_type parameter1, parameter2_type parameter2, ...) {
// Initialize data members with parameters
}
};
Simple Example
#include <iostream>
using namespace std;
class Rectangle {
private:
double length;
double width;
public:
// Parameterized constructor
Rectangle(double l, double w) {
length = l;
width = w;
}
double area() {
return length * width;
}
void display() {
cout << "Length: " << length << ", Width: " << width << endl;
cout << "Area: " << area() << endl;
}
};
int main() {
// Creating objects with specific values
Rectangle rect1(5.0, 3.0);
Rectangle rect2(7.5, 4.2);
rect1.display();
rect2.display();
return 0;
}
Ways to Call a Parameterized Constructor
There are two ways to call a parameterized constructor:
1. Direct Initialization (Using Parentheses)
Rectangle rect1(5.0, 3.0); // Direct initialization
2. Copy Initialization (Using Assignment Operator)
Rectangle rect2 = Rectangle(7.5, 4.2); // Copy initialization
Using Initialization Lists
A better way to initialize class members in a constructor is to use an initialization list:
class Student {
private:
string name;
int rollNumber;
float marks;
public:
// Parameterized constructor with initialization list
Student(string n, int r, float m) : name(n), rollNumber(r), marks(m) {
cout << "Student object created" << endl;
}
void display() {
cout << "Name: " << name << ", Roll: " << rollNumber;
cout << ", Marks: " << marks << endl;
}
};
Initialization lists are preferred because:
- They are more efficient (direct initialization vs. assignment)
- They are required for const members and reference members
- They make the constructor code cleaner and more readable
Parameterized Constructor with Default Arguments
You can provide default values for constructor parameters, making some or all parameters optional:
class Box {
private:
double length;
double width;
double height;
public:
// Parameterized constructor with default arguments
Box(double l = 1.0, double w = 1.0, double h = 1.0) {
length = l;
width = w;
height = h;
}
double volume() {
return length * width * height;
}
};
int main() {
Box box1; // Uses all defaults: (1.0, 1.0, 1.0)
Box box2(5.0); // Uses (5.0, 1.0, 1.0)
Box box3(5.0, 3.0); // Uses (5.0, 3.0, 1.0)
Box box4(5.0, 3.0, 2.0); // Uses (5.0, 3.0, 2.0)
cout << "Volume of box1: " << box1.volume() << endl; // Output: 1
cout << "Volume of box2: " << box2.volume() << endl; // Output: 5
cout << "Volume of box3: " << box3.volume() << endl; // Output: 15
cout << "Volume of box4: " << box4.volume() << endl; // Output: 30
return 0;
}
Parameter Validation in Constructors
You can add validation logic in parameterized constructors to ensure objects are created with valid data:
class Circle {
private:
double radius;
public:
// Parameterized constructor with validation
Circle(double r) {
if (r > 0) {
radius = r;
} else {
radius = 1.0; // Default to a valid value
cout << "Warning: Invalid radius. Set to default value 1.0" << endl;
}
}
double area() {
return 3.14159 * radius * radius;
}
};
int main() {
Circle c1(5.0); // Valid radius
Circle c2(-3.0); // Invalid radius, will be set to 1.0
cout << "Area of c1: " << c1.area() << endl;
cout << "Area of c2: " << c2.area() << endl;
return 0;
}
Using Parameterized Constructors in Arrays
When creating an array of objects with a parameterized constructor, you need to:
- Provide default constructor (if you want empty array initialization)
- OR initialize each element separately
class Point {
private:
int x, y;
public:
// Default constructor (needed for arrays)
Point() : x(0), y(0) { }
// Parameterized constructor
Point(int a, int b) : x(a), y(b) { }
void display() {
cout << "(" << x << ", " << y << ")" << endl;
}
};
int main() {
// Creating array of 5 Points using default constructor
Point points1[5];
// Creating array with initialization
Point points2[3] = {
Point(1, 2), // Initializes points2[0]
Point(3, 4), // Initializes points2[1]
Point(5, 6) // Initializes points2[2]
};
// Display points
for (int i = 0; i < 3; i++) {
points2[i].display();
}
return 0;
}
Delegating Constructors (C++11 and later)
In modern C++, a constructor can call another constructor of the same class to avoid code duplication:
class Person {
private:
string name;
int age;
string address;
public:
// Main constructor that does all the work
Person(string n, int a, string addr) : name(n), age(a), address(addr) {
cout << "Main constructor called" << endl;
}
// Constructor that delegates to the main constructor
Person(string n, int a) : Person(n, a, "Unknown") {
cout << "Two-parameter constructor called" << endl;
}
// Another constructor that delegates
Person(string n) : Person(n, 0) {
cout << "One-parameter constructor called" << endl;
}
};
Common Mistakes with Parameterized Constructors
-
Forgetting that defining a parameterized constructor removes the compiler’s default constructor:
class Example { public: Example(int x) { /* ... */ } // No default constructor provided by compiler! }; int main() { Example e; // Error: no default constructor return 0; } -
Not validating input parameters:
class NegativeRadius { private: double radius; public: NegativeRadius(double r) { radius = r; // Doesn't check if r is negative! } }; -
Overwriting member initialization in the constructor body:
class Inefficient { private: int x, y; public: Inefficient(int a, int b) : x(0), y(0) { // Initialize to 0 x = a; // Then overwrite (inefficient) y = b; // Then overwrite (inefficient) } };
Best Practices for Parameterized Constructors
- Use initialization lists instead of assignments in the constructor body
- Validate input parameters to ensure objects are created in a valid state
- Provide default values for parameters when appropriate
- Use meaningful parameter names that clearly indicate their purpose
- Consider adding a default constructor if you provide parameterized constructors
- Keep constructors simple - focus on initialization, not complex operations
Summary
Parameterized constructors allow you to initialize objects with specific values at creation time. They help ensure objects start in a valid state and eliminate the need for separate setter calls after object creation. By using parameterized constructors effectively, you can create more robust and easier-to-use classes in C++.