Every object of a class created in a program is stored somewhere in the memory. This memory is automatically deallocated when the object is destroyed. A constructor allocates resources dynamic memory) to an object during its creation in addition to its property of initialization. Similarly, we should have a member function that deallocates the resources (dynamic memory) allocated to an object. Such counterpart (complement) to the constructor is called a Destructor in C++.
A Destructor in C++ is a member function having the same name as that of the constructor (which is the same as that of class). Still, it is preceded by a tilde (~) symbol and is executed automatically when an object of a class is destroyed. Destructors are used for reinitializing the objects which are initialized by the constructors. A destructor is used to destroy the objects that the constructors already create. Like a constructor, the destructor does not have any return type, not even void, as it is invoked automatically whenever an object goes out of scope. However, unlike constructors, the destructor does not accept any parameters because there is no mechanism to pass arguments to an object destroyed. A class can have only one destructor and hence cannot be overloaded.
The syntax of the destructor is shown below.
class CLASSNAME { ........ public: ~CLASSNAME();//Destructor Declaration .......... }; CLASSNAME:: ~CLASSNAME() //Destructor Definition { ........... //Destructor body }
The syntax shows that the destructor has the same name as that of the class but is “prefixed by a tilde (~) symbol from where it is distinguished from the same class’s constructor. The brackets after the destructor name show that it is a member function of a class. It must be noted that the destructor is declared in the public section of the class so that it is accessible to all its users.
If you don’t define a destructor explicitly in the class, the compiler will write one for you in the same way as the compiler generates the default constructor. The compiler-generated default destructor is primarily used for releasing the memory allocated to an object. But in certain situations, there is a need to define destructor explicitly in the class to perform some clean up of resources such as freeing memory allocated dynamically. The releasing of dynamically allocated memory for an object by the destructor will be discussed later. The destructor is also used for displaying the final values of an object before its destruction.
#include<iostream.h> #include<conio.h> class counter { int id; public: counter(int i) { id=i; cout<<"\nconstructor of object with id" <<id<<" runs"; } ~counter() { cout<<"\nobject with Id"<< id<< " destroyed"; } }; int main() { clrscr(); counter c1(1); counter c2(2) ; counter c3(3); cout<<"\nEnd of main"; return 0; } Output: Constructor of object with Id 1 runs Constructor of object with Id 2 runs Constructor of object with Id 3 runs End of main Object with Id=3 destroyed Object with Id=2 destroyed Object with Id=1 destroyed
Explanation: In the above program, the class counter contains a data member id and two public member functions, including a constructor with one parameter and a destructor. In the main(), we have created and initialized three objects, c1, c2 and c3, of the class counter bypassing values 1, 2, 3 respectively to constructor with one parameter.
We first define object c1 using the statement.
counter c1(1);
Here, object c1 is created and counter c1(1); a constructor that takes one parameter, is invoked automatically. The invocation initializes the data member id to 1 and displays the message constructor of object 1 runs. Similarly, when the other two objects c2 and c3, are defined, the constructors are invoked to initialize the required values and display the appropriate messages. We can see from the output that the constructor is invoked in the order of their object’s creation.
Similarly, whenever the objects leave the block they are defined, the destructor member function is invoked automatically. In the above program, whenever an object goes out of scope, i.e. it encounters the ending curly brace(}) of the function in which it is defined, then the destructor is invoked automatically. On invocation, it displays the appropriate message. It is clear from the output that objects are destroyed in the reverse order of their creation. So the object c3, which is created, at last, is the first one to get destroyed. It is followed by the destruction of object c2 and then of object c1.
The following are the key points while defining a class’s destructor.
• A destructor has the same name as that of the class to which it belongs, preceded by the tilde(~) sign.
• A destructor is executed automatically whenever the object’s of a class are destroyed. It neither takes any parameters nor returns any value.
• There is only one destructor in a class and hence cannot be overloaded.
• Destructor can be used to deallocate memory for an object.
• If you don’t explicitly provide a destructor of your own, then a compiler generates a default destructor for you.
• A destructor should be declared in the public section of a class.
• It cannot be declared static or const.
• Unlike constructor, destructor can be virtual.
• Destructors cannot be inherited, though a derived class can call the base class’s destructor.
• Programmer cannot access the address of the destructor.
• An object with a destructor cannot be used as a member of a union.