Polymorphism is a basic attribute of object-oriented, including static polymorphism (compile phase) and dynamic polymorphism (runtime phase). Static polymorphism mainly refers to the polymorphism of different function parameters, which is a polymorphic mechanism which can be recognized in the compile phase, while Run-time polymorphism is mainly used when the base class pointer points to the derived class object. The object functions of the derived class can be called directly through the base class pointer, which is, of course, implemented through virtual functions.
The purpose of the virtual function is to inform the system that the corresponding class object type can be automatically recognized in the function call, so that the corresponding class object can be invoked according to the type of the pointer, thus realizing the polymorphism of the function call. For destructors, the same applies to the above rules. If the destructor is not a virtual function, then when the function is called (when the object is deleted), only the destructor of the class that corresponds to the current object is invoked. This has no effect on directly defined objects, but for pointers that use the base class to point to derived classes, because the base class pointer is actually a base class type, Therefore, the destructor of the base class is only invoked by nature, which can result in a memory leak (because the destructor of the derived class is not invoked). So if you determine that there are base class pointers in your program that point to a derived class problem, you must specify the destructor of the base class as a virtual function so that the new object is removed correctly.
Here are a few sample programs for easy understanding:
Class clxbase{
Public
Clxbase () {};
~clxbase () {cout << "Output from the destructor of Class clxbase!" << Endl;
void DoSomething () {cout << ' do something in class clxbase! ' << Endl;
};
Class Clxderived:public clxbase{
Public
Clxderived () {};
~clxderived () {cout << "Output from the destructor of Class clxderived!" << Endl;
void DoSomething () {cout << ' do something in class clxderived! ' << Endl;
};
Sample program One:
int main () {
Clxbase Base;
Clxderived derived;
Base. DoSomething ();
Derived. DoSomething ();
return 0;
}
Run Result:
Do something in class clxbase!
Do something in class clxderived!
Output from the destructor of class clxderived!
Output from the destructor of class clxbase!
Output from the destructor of class clxbase!
Analysis:
From the above instance program, we can find that the normal constructed object, the destructor of the derived class will call the destructor of the base class actively, so there is no memory leak problem.
Example program two:
int main () {
clxderived *p = new clxderived;
P->dosomething ();
Delete p;
return 0;
}
Run Result:
Do something in class clxderived!
Output from the destructor of class clxderived!
Output from the destructor of class clxbase! Analysis:
From the results above, it is found that the pointer to a derived class is also a destructor of a derived class that runs the corresponding type of the pointer at the time of the destructor, and this destructor naturally invokes the destructor of the base class, so no memory leaks are generated.
Instance Program three:
int main () {
Clxbase *p = new clxderived;
P->dosomething ();
Delete p;
return 0;
}
Run Result:
Do something in class clxbase!
Output from the destructor of class clxbase!
Analysis:
From the above results, we can find that the base class pointer, when it is destructor, calls the destructor of the base class, even though it points to a derived class, but it still invokes the destructor of the base class, so if there is a memory space in the derived class that needs to be freed, it is bound to be freed, resulting in a memory leak.
Sample program Four:
Class clxbase{
Public
Clxbase () {};
Virtual ~clxbase () {cout << "Output from the destructor of Class clxbase!" << Endl;
virtual void dosomething () {cout << ' do something in class clxbase! ' << Endl;
};
Class Clxderived:public clxbase{
Public
Clxderived () {};
~clxderived () {cout << "Output from the destructor of Class clxderived!" << Endl;
void DoSomething () {cout << ' do something in class clxderived! ' << Endl;
};
int main () {
Clxbase *p = new clxderived;
P->dosomething ();
Delete p;
return 0;
Run Results:
Do something in class clxderived!
Output from the destructor of class clxderived!
Output from the destructor of class clxbase!
Analysis:
The results above can be found whether it's a normal member function or a destructor, only a virtual function is defined to call the response function of the object when the base class pointer points to the derived class object, so that when the function is destructor, the new object is deleted correctly and no memory leaks are generated.