You might have already know what is a constructor is, so why read this. Here you deep dive into different types of constructors, copy constructor
is one good stuff to have a look. credits@gfg
- details
- Types of constructors
- Private constructors
- Private destructors
- Virtual Destructor
A constructor is a member function of a class which initializes objects of a class. In C++, Constructor is automatically called when object(instance of class) create. It is special member function of the class.
- Constructor has same name as the class itself
- Constructors don’t have return type
- A constructor is automatically called when an object is created.
- If we do not specify a constructor, C++ compiler generates a default constructor for us (expects no parameters and has an empty body).
Let us understand the types of constructors in C++ by taking a real-world example. Suppose you went to a shop to buy a marker. When you want to buy a marker, what are the options? The first one you go to a shop and say give me a marker. So just saying give me a marker mean that you did not set which brand name and which color, you didn’t mention anything just say you want a marker. So when we said just I want a marker so whatever the frequently sold marker is there in the market or in his shop he will simply hand over that. And this is what a default constructor is! The second method you go to a shop and say I want a marker a red in color and XYZ brand. So you are mentioning this and he will give you that marker. So in this case you have given the parameters. And this is what a parameterized constructor is! Then the third one you go to a shop and say I want a marker like this(a physical marker on your hand). So the shopkeeper will see that marker. Okay, and he will give a new marker for you. So copy of that marker. And that’s what copy constructor is!
Default constructor is the constructor which doesn’t take any argument. It has no parameters.
#include <iostream>
using namespace std;
class construct
{
public:
int a, b;
// Default Constructor
construct()
{
a = 10;
b = 20;
}
};
t is possible to pass arguments to constructors. Typically, these arguments help initialize an object when it is created. To create a parameterized constructor, simply add parameters to it the way you would to any other function. When you define the constructor’s body, use the parameters to initialize the object.
#include <iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
// Parameterized Constructor
Point(int x1, int y1)
{
x = x1;
y = y1;
}
int getX()
{
return x;
}
int getY()
{
return y;
}
};
A copy constructor is a member function which initializes an object using another object of the same class.
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x1, int y1) { x = x1; y = y1; }
// Copy constructor
Point(const Point &p2) {x = p2.x; y = p2.y; }
int getX() { return x; }
int getY() { return y; }
};
int main()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1; // Copy constructor is called here
// Let us access values assigned by constructors
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
return 0;
}
So why would you ever need this ?
#include <iostream>
using namespace std;
class xboxController
{
public:
int *m_Id;
public:
xboxController(int id)
{
m_Id = new int(id);
}
void get_Id()
{
cout << *m_Id << endl;
}
void set_Id(int new_id)
{
*m_Id = new_id;
}
};
int main()
{
xboxController x1(90221);
x1.get_Id();
// let's copy
xboxController x2 = x1;
x2.get_Id();
// let's change the value
x1.set_Id(40211);
// let's check what happened
x1.get_Id();
x2.get_Id();
}
Ouput:
90221
90221
40211
40211
But why?
What default class does while copying is similar to what you see below. It invokes this constructor.
xboxController(const xboxController& other)
: m_Id(other.m_Id)
{}
This caused the trouble, the pointer is basically copied instead of creating a new memory.
What we can do is define our own copy constructor so we can controll all the stuff while copying.
xboxController(const xboxController& other)
{
// New memory location is allocated
m_Id = new int(*(other.m_Id));
}
Constructor is automatically called when the object is created. If it is private then obviously there is error. So how can we access the private constructor.
-
Using Friends class
#include <iostream> using namespace std; // class A class A{ private: A(){ cout << "constructor of A\n"; } // Please note; friend class B; }; // class B, friend of class A class B{ public: B(){ // private fn of A can be accessed inside B A a1; cout << "constructor of B\n"; } };
-
Using Singleton design pattern : When we want to design a singleton class. This means instead of creating several objects of class, the system is driven by a single object or a very limited number of objects.
-
Named Idiom : Not much that interesting so I copied exactly from GFG
// CPP program to demonstrate
// named constructor idiom
#include <iostream>
#include <cmath>
using namespace std;
class Point
{
private:
float x1, y1;
Point(float x, float y)
{
x1 = x;
y1 = y;
};
public:
// polar(radius, angle)
static Point Polar(float, float);
// rectangular(x, y)
static Point Rectangular(float, float);
void display();
};
// utility function for displaying of coordinates
void Point :: display()
{
cout << "x :: " << this->x1 <<endl;
cout << "y :: " << this->y1 <<endl;
}
// return polar coordinates
Point Point :: Polar(float x, float y)
{
return Point(x*cos(y), x*sin(y));
}
// return rectangular coordinates
Point Point :: Rectangular(float x, float y)
{
return Point(x,y);
}
int main()
{
// Polar coordinates
Point pp = Point::Polar(5.7, 1.2);
cout << "polar coordinates \n";
pp.display();
// rectangular coordinates
Point pr = Point::Rectangular(5.7,1.2);
cout << "rectangular coordinates \n";
pr.display();
return 0;
}
Why ?
Whenever we want to control destruction of objects of a class, we make the destructor private. For dynamically created objects, it may happen that you pass a pointer to the object to a function and the function deletes the object. If the object is referred after the function call, the reference will become dangling.
Dangling -> pointing to already deleted location.
// CPP program to illustrate
// Private Destructor
#include <iostream>
using namespace std;
class Test {
private:
~Test() {}
};
Then how to use the class
Test t;
The compiler notices that the local variable ‘t’ cannot be destructed because the destructor is private.
A.cpp: In function ‘int main()’:
A.cpp:11:10: error: ‘Test::~Test()’ is private within this context
11 | Test t1;
| ^~
A.cpp:4:9: note: declared private here
4 | ~Test() {}
|
Then how can we use it ?
Test* t = new Test;
Now the user is responsible for deleting the object, but how could you ? delete t
will call the destructor, it is private, so error.
Then how ? we have to use a friend function for help.
// CPP program to illustrate
// Private Destructor
#include <iostream>
// A class with private destuctor
class Test {
private:
~Test() {}
friend void destructTest(Test*);
};
// Only this function can destruct objects of Test
void destructTest(Test* ptr)
{
delete ptr;
}
int main()
{
// create an object
Test* ptr = new Test;
// destruct the object
destructTest(ptr);
return 0;
}
We need vitual functions when the base and derived class have same function declaration. What about Destructor. When object get deleted, which destructor get called ? As you might suspect it calls the base destructor. So the data allocated for the derived class still exist causing memory leak.
class Base
{
public:
Base() {}
~Base() {}
};
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
};
int main()
{
Derived* d1 = new Derived;
Base* b1 = d1;
delete b1; // Here the destructor of base class is called
}
Solution is virtual function
// in base class
virtual ~Base() {}
// thats it folks we have avoided a nuclear explosion. Fwee!!