Use analysis of C++ virtual destructor

  • 2020-04-02 01:00:12
  • OfStack

In C++, you cannot declare an imaginary constructor, but you can declare a virtual destructor. Polymorphism refers to the fact that different objects have different behavior characteristics for the same message. Virtual functions, which are the basis of runtime polymorphism, are primarily targeted at objects, while constructors run before objects are generated, so it makes no sense to invent functions.
The function of destructors is to do the necessary cleanup before the class dies, and destructors are ideally virtual.
First, explain how fictional functions and Pointers interact, and what virtual destructors mean. For example, the following code, where SomeClass is a class with a non-virtual destructor:
SomeClass * p = new SomeClass;
.   .
Delect p;
When delect is called for p, the destructor of the SomeClass class is automatically called. Now, let's see what happens when you mark the destructor as virtual.
The simplest way to describe how destructors interact with the virtual function mechanism is to treat all destructors as having the same name (even if they are not really the same name). For example, assume that the Derived class is a Derived class of the Base class, and assume that the destructor in the Base class is marked virtual. Now let's analyze the following code:
The Base * pBase = new Derived;
.   .
Delect pBase;
When delect is called for Base, a destructor is called. Since the destructor in the Base class is marked as virtual and the object pointed to is of the Derived type, destructors in the Derived class are called.
It is important to note that when destructors are marked as virtual, all destructors of derived classes automatically become virtual (regardless of whether they are marked with virtual). Again, this behavior is as if all destructors have the same name (even if they actually have different names).
The following is the benefit of marking all destructors as virtual. Assuming that the Base class has a member variable pB of pointer type, the constructor of the Base class creates a dynamic variable pointed by pB, and the destructor of the Base class deletes the dynamic variable pointed by pB. In addition, it is assumed that the Base class is not marked as virtual and that the Derived class (which is Derived from Base) has a member variable pD of pointer type. The constructor of the Derived class will create a dynamic variable with pD pointing to it, while the destructor of the Derived class will delete the dynamic variable pointed to by pD. Analyze the following code:
The Base * pBase = new Derived;
.   .
Delect pBase;
Since the destructor in the Base class is not marked virtual, only the destructor of the Base class is called. It returns the memory occupied by the dynamic variable to free storage. However, for dynamic variables that pD points to, the memory it occupies is never returned to free storage (unless the program terminates).
On the other hand, if the destructor of the Base class is marked virtual, then when delect is called for pBase, the destructor of the Derived class is called (because the object pointed to is of the Derived type). The destructor of Derived class will delete the dynamic variable pointed by pD, and then automatically call the destructor of Base class. The latter removes the dynamic variable that pB points to. Therefore, with the base class destructor marked virtual, all memory can be successfully reclaimed by free storage. To prepare for this situation, it is always best to mark the destructor virtual.
Here's an example:

#include "stdafx.h"
#include <iostream>
using namespace std;
class Base
{
public:
 Base(){cout << " Constructor in Base. " << endl;}
 virtual ~Base(){ cout << " Destructor in Base. " << endl;}
};
class Derived:public Base
{
public:
 Derived(){cout << " Constructor in Derived. " << endl;}
 ~Derived(){cout << "Destructor in Derived. " << endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
 Base *p = new Derived;
 delete p;
 return 0;
}

Output:
      The Constructor in the Base.
      The Constructor in Derived.
      Destroctor Derived in.
      Destroctor in Base.
 
If the destructor in Base has no virtual decoration, the output is:
        The Constructor in the Base.
        The Constructor in Derived.
        Destroctor in Base.
If the destructor in such subclass Derived is not executed, it will cause memory leak. Therefore, if a class is the base class of other classes, its destructor should be declared as virtual destructor. In addition, the execution order of constructor and destructor can be seen from this example. Constructor, base class before subclass, destructor, subclass before base class.

Related articles: