Welcome to the lesson on Constructors in C++ classes!
Have you ever wondered how objects in your code are created and initialized? This is where constructors come into play. Constructors are special functions that are automatically called when an object of a class is created. They help set up the object with initial values and are essential for managing resources efficiently. In this lesson, our goal is to understand different types of constructors in C++: default
, parameterized
, and copy constructors
, and learn how to implement them in a class.
So, what exactly is a constructor? A constructor is a special member function of a class that initializes objects. It has the same name as the class and does not have a return type, not even void
.
Think of a constructor like setting up a new house. When you move in, you need to set up the furniture before you can comfortably live in it. Similarly, when an object is created, a constructor sets up the initial state of the object.
A default constructor
is a constructor that either has no parameters or has parameters with default values. Its primary purpose is to initialize objects with default settings.
Let's see how to write a default constructor using an example:
C++1#include <iostream> 2 3class MyClass { 4public: 5 // Default constructor 6 MyClass() { 7 std::cout << "Default constructor called!" << std::endl; 8 } 9}; 10 11int main() { 12 MyClass obj; // Default constructor is called here 13 return 0; 14}
In this example, when we create an object obj
of MyClass
, the default constructor is called, displaying the message "Default constructor called!".
Parameterized constructors
help when you need to initialize objects with specific values. These constructors accept arguments to initialize an object with provided values.
Let's extend our previous example:
C++1#include <iostream> 2 3class MyClass { 4public: 5 int value; 6 7 // Default constructor 8 MyClass() { 9 value = 0; 10 std::cout << "Default constructor called!" << std::endl; 11 } 12 13 // Parameterized constructor 14 MyClass(int param) { 15 value = param; 16 std::cout << "Parameterized constructor called! Value: " << value << std::endl; 17 } 18}; 19 20int main() { 21 MyClass obj1; // Default constructor is called 22 MyClass obj2(100); // Parameterized constructor is called 23 return 0; 24}
Here, obj1
uses the default constructor, and obj2
uses the parameterized constructor to initialize the value to 100.
In C++, this
is a keyword that refers to the current instance of the class. Inside a class member function, this
can be used to reference the calling object’s members. This is particularly useful in constructors to avoid naming conflicts between parameters and class members.
Let's consider an example:
C++1#include <iostream> 2#include <string> 3 4class BankAccount { 5public: 6 std::string accountHolderName; 7 int accountNumber; 8 double balance; 9 10 BankAccount(std::string param1, int param2, double param3) { 11 accountHolderName = param1; 12 accountNumber = param2; 13 balance = param3; 14 } 15}; 16 17int main() { 18 BankAccount acc("John Doe", 123456, 1000.50); 19 std::cout << "Account Holder: " << acc.accountHolderName << ", Account Number: " << acc.accountNumber << ", Balance: " << acc.balance << std::endl; 20 return 0; 21}
Here, naming parameters param1
, param2
and param3
is confusing and doesn't reflect the meaning of the variables. However, we can't call them accountHolderName
, accountNumber
and balance
, because it will cause naming conflict between the attributes and the parameters.
We can solve this problem using this
keyword:
C++1#include <iostream> 2#include <string> 3 4class BankAccount { 5public: 6 std::string accountHolderName; 7 int accountNumber; 8 double balance; 9 10 // Parameterized constructor using 'this' keyword 11 BankAccount(std::string accountHolderName, int accountNumber, double balance) { 12 this->accountHolderName = accountHolderName; 13 this->accountNumber = accountNumber; 14 this->balance = balance; 15 } 16}; 17 18int main() { 19 BankAccount acc("John Doe", 123456, 1000.50); 20 std::cout << "Account Holder: " << acc.accountHolderName << ", Account Number: " << acc.accountNumber << ", Balance: " << acc.balance << std::endl; 21 return 0; 22}
In this example, this->accountHolderName
specifies that we are referring to the class member accounHolderName
instead of the constructor parameter accounHolderName
. This way, we can call parameters the same way as the class members, making the code clearer.
A copy constructor
is used to initialize an object by copying another object of the same class. It is essential when you need to create a copy of an existing object.
Here’s how a copy constructor works:
C++1#include <iostream> 2 3class MyClass { 4public: 5 int value; 6 7 // Default constructor 8 MyClass() { 9 value = 0; 10 std::cout << "Default constructor called!" << std::endl; 11 } 12 13 // Parameterized constructor 14 MyClass(int value) { 15 this->value = value; 16 std::cout << "Parameterized constructor called! Value: " << value << std::endl; 17 } 18 19 // Copy constructor 20 MyClass(const MyClass &obj) { 21 value = obj.value; 22 std::cout << "Copy constructor called! Value: " << value << std::endl; 23 } 24}; 25 26int main() { 27 MyClass obj1(100); // Parameterized constructor is called 28 MyClass obj2 = obj1; // Copy constructor is called 29 return 0; 30}
Output:
1Parameterized constructor called! Value: 100 2Copy constructor called! Value: 100
In this example, obj2
is created as a copy of obj1
using the copy constructor. The value of obj1
is copied to obj2
.
Just like member functions, constructors can also be defined outside the class. Here is an example:
C++1#include <iostream> 2 3class Demo { 4public: 5 int value; 6 Demo(); 7}; 8 9Demo::Demo() { 10 value = 42; 11 std::cout << "Constructor defined outside the class. Value: " << value << std::endl; 12} 13 14int main() { 15 Demo demoObj; 16 return 0; 17}
In this example, the constructor for the Demo
class is defined outside the class using the scope resolution operator ::
. When demoObj
is created, the constructor is called and initializes value
to 42.
C++ also allows constructors to initialize members using a member initializer list. Here’s an example:
C++1#include <iostream> 2 3class Wheel { 4public: 5 int size; 6 7 // Constructor using member initializer list 8 Wheel(int s) : size(s) { 9 std::cout << "Wheel size: " << size << std::endl; 10 } 11}; 12 13int main() { 14 Wheel myWheel(15); // Member initializer list sets the size 15 return 0; 16}
Output:
1Wheel size: 15
In this example, Wheel(int s) : size(s) {}
is a constructor that uses the member initializer list to assign the value of s
to the member size
. This can be more efficient and is often used to initialize constant members or base classes in derived classes.
Let’s quickly compare the three types of constructors:
- Default Constructor:
- Initializes an object with default settings.
- No parameters.
- Parameterized Constructor:
- Initializes an object with specific values.
- Accepts arguments.
- Copy Constructor:
- Initializes an object by copying an existing object.
- Takes a reference to an object of the same class as a parameter.
Each type has its unique use case and is crucial for effective object initialization and management.
Congratulations! You've now learned about three different types of constructors in C++: default constructors
, parameterized constructors
, and copy constructors
. Constructors play a vital role in ensuring that objects are set up correctly with initial values. They simplify the process of managing resources and initializing objects, making your code more efficient and robust.
Now it's time for some hands-on practice! In the upcoming exercises, you will implement your own constructors in a sample class. This will give you the opportunity to apply what you've learned and see constructors in action. Happy coding!