A default constructor.
It has zero parameters (or all its parameters have defaults) so that an object can be constructed without any parameters.
If you do not define any constructors the compiler will generate a default constructor for you.
The compiler generated default constructor does (in the following order)
- Call the default constructor of all base classes (if any, but in order).
- Call the default constructor of each member (in the order they are declared in the class).
- If the member is a int/float/char etc it is undefined.
- If the member is a pointer it is undefined.
The copy constructor:
If you do not define a copy constructor then the compiler will generate a default copy constructor.
The compiler generate copy constructor does (in the following order)
- Call the copy constructor of all the base classes (if any, but in order).
- Call the copy constructor of each member (in the order they are declared in the class).
- Each member is passed the corresponding member of the object being copied.
- Note for pointers this means just copy the pointer value.
This is why we get the shallow copy problem when the class contains a RAW pointer that the object manages.
Though not a constructor. It is important to note that the compiler will also auto generate the assignment operator when one is not defined.
The compiler generated assignment operator does (in the following order)
- Call the assignment operator of each base class (if any, but in order).
- Call the assignment operator of each member (in the order they are declared in the class).
- Each member is passed the corresponding member of the object being copied.
- Note for pointers this means just copy the pointer value.
This is why we get the shallow copy problem when the class contains a RAW pointer that the object manages.
The default Destructor:
Most people think the destructor is trivial or not there. But it is important to note what the default version is actually doing (it is slightly more than nothing).
- Each member has its destructor called (in reverse order of declaration)
- Note int/float/pointers do not have destructors so nothing explicit is done.
- Each base class destructor is called in reverse order.
If you define a destructor the behavior does not change. But the code you define as part of the destructor is executed before the behavior defined above. So in affect there is always a destructor just the code is an empty block.
Note: There are some special considerations when virtual base classes are used. But that's another question.
So even if you define an empty class. The compiler will always generate four methods for you:
class X: public Z
{
int a;
Y b;
Z* c;
};
// Compiler generated methods will look like this:
X::X()
:Z() // Construct base class.
//,a?? The default construction of an int does nothing the value is undefined.
,b()
//,c?? The default construction of a pointer does nothing,
{}
X::~X()
{} // Note members are destoyed here
// ~c: Does nothing it is a pointer.
// ~b: destroyes b via Y::~Y()
// ~a: Does nothing as POD has not destructr.
// ~Z(): Destory base class.
X::(X const& rhs)
:Z(rhs)
,a(rhs.a)
,b(rhs.b)
,c(rhs.c)
{}
X& operator=(X const& rhs)
{
Z::operator=(rhs);
a = rhs.a;
b = rhs.b;
c = rhs.c;
return *this;
}