C++ Constructors and types of Constructors with example
C++ Constructors:
A C++ constructor is a member function of a class that is called and executed automatically when an object of that class is created. The name of the constructor function is the same as the name f the class itself.
A constructor function may have arguments but it cannot return any value.
Example: how to create a c++ constructors in programming:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> using namespace std; class data { public: data() { cout<<" Programming digest"<<endl; } }; int main() { data a, b,c; return 0; } |
Output:
1 2 3 4 |
<span style="font-family: georgia, palatino, serif;">Programming digest Programming digest Programming digest </span> |
In the above program, the class “data” contains member function “data”. This member function is the c++ constructors function because the name of this function and the name of the class are the same. When the member function “data” is executed, it prints “programming digest” on the computer screen.
In the program, three objects (a,b, and c) of the class “data are created. Each time an object f the class “data” is created, the constructor is executed and the word “ programming digest” is printed on the computer screen. Since three objects are created, the word programming digest is printed three times.
Initializing data using C++ Constructors:
The constructor functions are normally used to initialize values in data members of a class when the program is executed. This type of initialization is called automatic initialization.
For example, if the member function has two arguments of int type, the specified values can be assigned to the data member of the class using a constructor as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using namespace std; class sum { private: int n, m, s; public: sum(int x, int y) { n=x; m=y; s=n+m; } data () { cout<<"Sum of "<<n<<"and"<<m<<"is"<<s<<endl; } }; int main() { sum a(17,40); sum b(6,9); a.data(); b.data(); return 0; } |
Output:
1 2 |
<span style="font-family: georgia, palatino, serif;">Sum of 17 and 40 is 57 Sum of 6 and 9 is 15</span> |
In the above program when the object “a” of the class “sum” is created, the control shifts to the constructor function “sum”. The c++ constructor function assigns values to variables n and m and its also calculates their sum. Thus when data function is executed by the object a, the values assigned to the data members of the object by the constructor are printed.
Similarly when the object b is created, the c++ constructor function is automatically executed.
C++ constructors Overloading:
More than one c++ constructor function can be defined in one class when more than one c++ constructors function are defined, each c++ constructors is defined with a different set of parameters. Defining more than one constructor with different set of parameters is called c++ constructors overloading.
When a program that uses the c++ constructors overloading is compiled, c++ compiler checks the number of parameters, their order and data types and marks them differently. When an object of the class is created, the corresponding c++ constructors that matches the number of parameters of the object function is executed.
In the following example, two constructors functions are defined in class “sum”
Example how to use c++ constructors overloading in programming:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> using namespace std; class sum { public: sum(int l, int m, int n) { cout<<"sum of 3 integers is= "<<(l+m+n)<<endl; } sum(int l, int m) { cout<<"sum of 2 integers is"<<(l+m)<<endl; } }; int main() { sum x(4,5), y(2,3,5); return 0; } |
Output:
1 2 |
<span style="font-family: georgia, palatino, serif;">sum of 2 integers is9 sum of 3 integers is= 10</span> |
when the program is executed, the object x is created first and them the sum constructor function that has only two integer type parameters is executed.
Then the y object is created. It has three parameters of integer type so the c++ constructors function that has three arguments of integer type is executed.
Example how to use constructors overloading function in c++ Programming:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include <iostream> using namespace std; class find { private: int mx; public: find(int x, int y, int z) { if(x>y) if (x>z) mx=x; else mx=z; else if (y > z) mx=y; else mx=z; cout<<"Maximum between three number is : "<<mx<<endl; } find(int x, int y) { if(x>y) mx=x; else mx=y; cout<<"maximum between two number is : "<<mx<<endl; } }; int main() { int a=30, b=49, c=90; find data(a,b); find datas(c,b,a); return 0; } |
programm Explanation:
This C++ code defines a class named find with two constructors. The first constructor is a parameterized constructor that takes three integer arguments x, y, and z. It finds the maximum of these three numbers and stores it in the private member variable mx. Then, it prints a message to the console indicating the maximum number.
The second constructor is also a parameterized constructor that takes two integer arguments x and y. It finds the maximum of these two numbers and stores it in the private member variable mx. Then, it prints a message to the console indicating the maximum number.
In the main() function, two objects of the find class are created using the two constructors. The first object data is created with two integer arguments a and b, and the second object datas is created with three integer arguments c, b, and a.
When the first object data is created, the second constructor is called, which finds the maximum between a and b and prints the result. When the second object datas is created, the first constructor is called, which finds the maximum between c, b, and a and prints the result.
The output of the program will be:
1 2 |
<span style="font-family: georgia, palatino, serif;">maximum between two number is : 49 Maximum between three number is : 90</span> |
Types of C++ Constructors:
Parameterized constructors
C++ Constructors that can take at least one argument are termed as parameterized C++ constructors. When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. The normal way of object declaration may not work. The constructors can be called explicitly or implicitly. The method of calling the constructor implicitly is also called the shorthand method. If we want to initialize fields of the class with your own values, then use a parameterized C++ constructor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Example { public: Example(); Example(int a, int b); // Parameterized constructor. private: int x_; int y_; }; Example::Example() = default; Example::Example(int x, int y) : x_(x), y_(y) {} Example e = Example(0, 50); // Explicit call. Example e2(0, 50); // Implicit call. |
Default constructors
If the programmer does not supply a constructor for an instantiable class, Java compiler inserts a default constructor into your code on your behalf. These c++ constructors is known as the default constructor. You would not find it in your source code (the java file) as it would be inserted into the code during compilation and exists in .class file. The behavior of the default constructor is language dependent. It may initialize data members to zero or other same values, or it may do nothing at all. In Java, a “default constructor” refer to nullary c++ constructors that is automatically generated by the compiler if no constructors have been defined for the class or in the absence of any programmer-defined constructors (e.g. in Java, the default constructor implicitly calls the superclass’s nullary constructor, then executes an empty body). All fields are left at their initial value of 0 (integer types), 0.0 (floating-point types), false (boolean type), or null (reference types).
1 2 3 4 5 6 7 8 9 |
#include <iostream> class Student { public: Student(int a = 0, int b = 0); // Default constructor. int a; int b; }; |
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> using namespace std; class Box { public: int Volume() {return m_width * m_height * m_length;} private: int m_width { 0 }; int m_height { 0 }; int m_length { 0 }; }; int main() { Box box1; // Invoke compiler-generated constructor cout << "box1.Volume: " << box1.Volume() << endl; // Outputs 0 } |
Programm Explanation:
This C++ code defines a class named Box with a default constructor. The class has three private member variables m_width, m_height, and m_length, and a public member function Volume which returns the volume of the box calculated by multiplying the three variables.
The default constructor is a constructor that takes no arguments. In this code, the default constructor is compiler-generated because the user did not define any constructor explicitly. The default constructor initializes the three member variables m_width, m_height, and m_length to their default values, which are 0 in this case.
In the main() function, an object box1 of the Box class is created using the default constructor. When box1 is created, the default constructor is called implicitly to initialize the member variables to their default values.
The program then calls the Volume member function of the box1 object, which calculates and returns the volume of the box by multiplying the three member variables. However, since the three member variables were initialized to 0 by the default constructor, the output of box1.Volume() will be 0.
The output of the program will be:
1 |
box1.Volume: 0 |
Copy constructors in c++:
In C++, a copy constructor is a special constructor that is used to create a new object as a copy of an existing object of the same class. It is called when an object is initialized with another object of the same class, either by direct initialization or by passing an object as a function argument by value.
A copy constructor takes a reference to an object of the same class as a parameter and creates a new object that is a copy of the referenced object. The copy constructor is typically defined with the following signature:
1 |
ClassName(const ClassName& other) |
where ClassName
is the name of the class, and other
is the reference to the object that is being copied.
Implicit copy constructor in c++:
In C++, an implicit copy constructor is a constructor that is generated by the compiler automatically when a class does not have any user-defined copy constructor.
The implicit copy constructor is responsible for creating a copy of an object when an object is passed by value, returned from a function, or assigned to another object using the assignment operator.
The implicit copy constructor creates a new object that is a copy of the original object, member-wise. It copies all non-static member variables of the original object into the new object.
For example, consider the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Person { public: int age; }; int main() { Person p1; p1.age = 25; Person p2 = p1; // Implicit copy constructor is called std::cout << p2.age; // Output: 25 return 0; } |
In the above code, p1
is an object of the Person
class. When p1
is copied to p2
using the assignment operator, the implicit copy constructor is called. It copies the value of the age
member variable from p1
to p2
. Thus, the output of the above code will be 25
.
It is important to note that the implicit copy constructor only performs a shallow copy of the object’s member variables. If a class contains pointers to dynamically allocated memory, the implicit copy constructor will copy the pointer, but not the memory it points to. In this case, a user-defined copy constructor should be provided to ensure that the memory is properly copied.
User-defined copy constructor in c++:
In C++, a user-defined copy constructor is a constructor that is defined by the programmer to create a copy of an object of a class. It is used to ensure that a deep copy of the object is made, especially when the object contains dynamically allocated memory.
To define a user-defined copy constructor in C++, the following steps can be followed:
Declare a copy constructor in the class definition. The copy constructor should take a reference to an object of the same class as a parameter.
1 2 3 4 |
class MyClass { public: MyClass(const MyClass& other); }; |
Define the copy constructor outside the class definition. The copy constructor should make a deep copy of the object by copying all member variables, including any dynamically allocated memory.
1 2 3 4 5 6 7 |
MyClass::MyClass(const MyClass& other) { // Copy all member variables this->memberVar = other.memberVar; // If any memory was dynamically allocated, copy it here this->ptr = new int(*other.ptr); } |
Here’s an example program that shows the use of a user-defined copy constructor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <iostream> class MyClass { public: MyClass(int x) { ptr = new int(x); } // User-defined copy constructor MyClass(const MyClass& other) { ptr = new int(*other.ptr); } ~MyClass() { delete ptr; } void Print() { std::cout << "Value of ptr = " << *ptr << std::endl; } private: int* ptr; }; int main() { MyClass obj1(10); obj1.Print(); MyClass obj2 = obj1; // Copy constructor called obj2.Print(); obj1.~MyClass(); // Destructor called to delete obj1's memory obj2.Print(); // obj2's memory is not affected by obj1's destructor return 0; } |
In this program, the MyClass class contains a pointer to dynamically allocated memory. The user-defined copy constructor makes a deep copy of the object by allocating new memory and copying the value of the pointer.
When obj1 is copied to obj2, the user-defined copy constructor is called, and a deep copy of obj1 is made. The program then calls the destructor of obj1 to delete its memory. However, the memory of obj2 is not affected, as it was copied and allocated separately.
The output of the above program will be:
1 2 3 |
Value of ptr = 10 Value of ptr = 10 Value of ptr = 10 |
Conversion constructors in C++
In C++, a conversion constructor is a special type of constructor that is used to convert one data type to another. It allows a class to be used in contexts where another type is expected, by defining how objects of the class can be constructed from other types.
To define a conversion constructor in C++, the following steps can be followed:
Declare a constructor with a single parameter of a different type from the class.
1 2 3 4 |
class MyClass { public: MyClass(int x); }; |
Define the constructor outside the class definition.
1 2 3 4 |
<span style="font-family: georgia, palatino, serif;">MyClass::MyClass(int x) { // Initialize class members with converted value memberVar = x * 2; }</span> |
Here’s an example program that shows the use of a conversion constructor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> class MyClass { public: MyClass(int x); void Print() { std::cout << "Value of memberVar = " << memberVar << std::endl; } private: int memberVar; }; MyClass::MyClass(int x) { memberVar = x * 2; } int main() { MyClass obj = 5; // Conversion constructor called obj.Print(); return 0; } |
In this program, the MyClass class has a conversion constructor that takes an integer value x. The constructor initializes the memberVar variable of the class with the value of x multiplied by 2.
When the statement MyClass obj = 5; is executed, the conversion constructor is called automatically to convert the integer value 5 to an object of type MyClass. The resulting object has its memberVar variable initialized with the value 10.
The output of the above program will be:
1 |
Value of memberVar = 10 |
Move constructor in C++
In C++, a move constructor is a special member function of a class that enables the transfer of ownership of an object’s resources, such as memory buffers, from one object to another. It is typically used to optimize the performance of certain operations, such as returning a large object from a function or resizing a container.
A move constructor is defined with the following syntax:
1 2 3 4 |
class MyClass { public: MyClass(MyClass&& other); // Move constructor }; |
The move constructor takes a single argument, which is an rvalue reference to another object of the same class. The rvalue reference indicates that the object being passed in can be safely modified or moved from, since it is not being used elsewhere.
Here’s an example program that shows the use of a move constructor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <iostream> class MyArray { public: MyArray(int size) : size_(size), data_(new int[size]) { for (int i = 0; i < size; i++) { data_[i] = i + 1; } } // Move constructor MyArray(MyArray&& other) { data_ = other.data_; size_ = other.size_; other.data_ = nullptr; other.size_ = 0; } // Destructor ~MyArray() { delete[] data_; } // Getter for the size of the array int size() const { return size_; } // Index operator overload int operator[](int index) const { return data_[index]; } private: int size_; int* data_; }; int main() { MyArray arr1(5); // Create an array of size 5 MyArray arr2(std::move(arr1)); // Move arr1 to arr2 // Attempting to use arr1 here would result in undefined behavior, // since its data has been moved to arr2 and its destructor has been called std::cout << "arr2 size: " << arr2.size() << std::endl; // Outputs "arr2 size: 5" std::cout << "arr2[2]: " << arr2[2] << std::endl; // Outputs "arr2[2]: 3" return 0; } |
In this example, we define a MyArray class that represents a dynamically allocated array of integers. The class has a move constructor that takes an rvalue reference to another MyArray object. The move constructor simply swaps the data_ and size_ members with the other object, and sets the other object’s members to null or 0.
In the main() function, we create two MyArray objects, arr1, and arr2. arr1 is initialized with a size of 5, and its elements are populated with the values 1 through 5. arr2 is constructed by moving arr1 using the std::move() function.
After the move, arr1 is in an unspecified state, as its members have been modified by the move constructor. Attempting to use arr1 after the move would result in undefined behavior, since its memory has been moved to arr2.
Finally, we output the size and value of an element of arr2, to demonstrate that arr2 has been properly initialized with the data from arr1.
The output of the above program will be:
1 2 |
<span style="font-family: georgia, palatino, serif;">arr2 size: 5 arr2[2]: 3</span> |