A constructor is a special member function that is automatically called when you create an instance of a class.
A constructor has the same name as the class and does not have a return type. If you have not defined any constructor yourself, then the compiler will implicitly create a default constructor for you. But if you have defined at least one constructor, then the compiler will not create a default constructor.
A class can have any number of constructors (constructor overloading) since C++ supports function overloading. You can define three types of constructors.
- A default constructor that does not take any arguments.
- A parameterized constructor that takes arguments.
- A copy constructor that is implicitly created by the compiler. A copy constructor is used to create an object from an existing object of the class. The default copy constructor (created by the compiler) is more than sufficient if the class does not contain any dynamically allocated objects. The default copy constructor performs shallow copy which works well with basic types but can create issues if you have dynamically allocated members, pointer, file handles etc. In such cases, you will need to create your own custom copy constructor that performs deep copy.
class Example{ int member_variable; public: Example(){} //Default Constructor Example(int val){ //Parameterized Constructor member_variable = val; } Example(const Example &other){ //Copy Constructor member_variable = other.member_variable; } };
If you have an object of another class in your class definition, the former class is constructed before the latter (when you create an instance of your class). This is so because your class might need to use the former class’s object while it is being constructed and this is only possible if the former has already been constructed.
#include <iostream> | |
using namespace std; | |
class Example1 { | |
public: | |
Example1() { cout << "Inside Example 1\n"; } | |
}; | |
class Example2{ | |
Example1 e1; | |
public: | |
Example2() { cout << "Inside Example 2\n"; } | |
}; | |
int main() { | |
Example2 e2; | |
cin.get(); | |
} |
Output:
Inside Example 1 Inside Example 2
In the above example, Example2 was able to construct an instance of Example1 only because Example1 had a default constructor defined. If Example1 did not have a default constructor defined implicitly or explicitly (like in our example), the programmer would have had to call the parameterized constructor of Example1 from within the member initializer list of Example2.
#include <iostream> | |
using namespace std; | |
class Example1 { | |
public: | |
Example1(int a) { cout << "Inside Example 1\n"; } | |
}; | |
class Example2{ | |
Example1 e1; | |
public: | |
Example2():e1(2) { cout << "Inside Example 2\n"; } | |
}; | |
int main() { | |
Example2 e2; | |
cin.get(); | |
} |
You can’t assign values for const and reference members by assignment(=) inside a constructor. You need to use a member initializer list for this. This is so because const and reference variables must be initialized when they are defined.
class Example{ const int val; string& name; public: //This is in-correct. //Example(int a, string& b){ val = a;name = b;} //This is correct Example(int a, string& b):val(a),name(b){} };
If you decide to write a custom copy constructor for your class, it is useful to remember the following rule. The Rule of Three is a rule of thumb for C++ which is stated as follows
If your class needs any of a copy constructor, an assignment operator, or a destructor, defined explicitly, then it is likely to need all three of them.
When you create a class instance, you can perform direct initialization (‘()’), uniform initialization(from C++11, ‘{}’) or copy initialization (rarely used).
class Example{ int member_variable; public: Example(int val):member_variable(val){} }; int main(){ //Direct Initialization Example e1(10); Example e2 = 10; //Uniform Initialization Example e3{10}; Example e3= {10} }
Constructors can be marked as default or delete. A constructor is marked as default if we need its default implementation. This is useful when we need the default implementation of the default constructor along with a parameterized constructor. A constructor that is marked for delete cannot be called.
class Example1{ public: Example1()=delete; } class Example2{ int member_variable; public: Example2()=default; Example2(int a):member_variable(a){} } int main() { Example1 e1; //error Example2 e2; //correct Example2 e3(2);//correct cin.get(); }
Remember that if a constructor is declared as private in a class, then you will not be able to create an instance of that class. Singleton Classes have private constructors (or constructors marked for delete). In C++11 and above, constructors can call other constructors. This is called as delegating constructors (or constructor chaining). To have one constructor call another, call the constructor in the member initializer list. Always make sure that you are calling the constructor from the member initializer list, not in the body of the constructor.
Assignment operator and Copy Constructor
Assignment operator is used to copy an object into an existing object. The purpose of the copy constructor and the assignment operator are almost equivalent — both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.
Both assignment operator and copy constructor have default versions. But the default versions only perform shallow copy of the data. In order to perform deep copy, we need to define an explicit copy constructor or overload the assignment operator. Just like other constructors and operators, we can prevent assignments from being made by making your assignment operator and copy constructor private.
When you pass an object as a function argument, copy constructor is used to copy the contents.
Unlike many other langues, C++ does not have a static constructor. So you cannot use a constructor to initialize a static member variable.
Leave a Reply