What kind of situations require a virtual destructor?
Classes need to control what happens when their objects perform a series of operations, including creating (objects), copying, moving, assigning, and destroying. In an inheritance system, if a class (the base class or its derived class) does not have a copy control operation defined, the compiler automatically synthesizes one for it. That is the copy control of the composition .
In the copy control of the base class , the biggest effect due to the inheritance relationship is that the base class should typically define a ' virtual destructor '. Used to dynamically allocate objects in the inheritance system.
such as: Class A,b,c,d has the following inheritance relationship (code 1):
1234 |
class A; class B: public A; class C: public B; class D: public C; |
Where: Class A is defined as follows (Code 2):
12345 |
class a { public :      //other functions      virtual ~a () = default //a destructor for dynamic binding } |
When we delete a * Item -type pointer, the pointer may point to a, or it may point to one of the b,c,d, and the compiler must be clear at the time of the delete that the destructor of which class in a,b,c,d should be executed. At this point the compiler is required to bind dynamically (that is, only the runtime knows exactly what the item is pointing to). When the destructor defined in base class A is a virtual destructor, the derived class of a (B,C,D) uses a composite destructor or a destructor of its own definition, which are virtual destructors. Say the word is: your old ancestral surname virtual, to you or the surname virtual, your son grandson all have to surname virtual (do not seriously girls ~ ~ ~), regardless of the descendants of your blood or your own adoption, all have to be empty!
As an example (Code 3):
1234 |
A *item = new A; //此时item指向的就是A,静态类型于动态类型一致(这就是你本人) delete item; //调用A自己的析构函数(自杀了,杀的是你自己) item = new B; //静态类型为A,动态类型为B(此时你的血脉传到了你儿子身上,item是你儿子了!) delete item; //调用B自己的析构函数(你儿子要自杀,此时死的是你儿子,和你无关) |
If the destructor of base class A is not virtual (virtual function), then delete, if item points to a derived class other than a, but B or other A, produces undefined behavior, which usually results in a bug.
So the question is: What kind of situation does it take to have a virtual destructor? Are all classes supposed to have it?
When you delete an object of a derived class from a pointer to a base class , the destructor for the base class should be virtual . Otherwise its delete effect will not be implemented.
Simply explain that all of the properties in the derived Class B operate (Bp) with not only the properties, operations (BSELF) that are defined by B itself, but also attributes, operations (aself) that inherit from a, i.e. bp=bself+aself;
As in code 3, when delete is a pointer to item B (In fact, the class type of item is a), if the destructor in a is not virtual, only the aself part is deleted, because the class type of item is actually a, but it points to its derived class object. But in A's destructor there is actually no bself part, then this part will be deleted-this is called a memory leak! Only A's destructor is virtual, can delete not only have aself, also have bself, namely BP all is deleted. That is the right thing to do.
At the same time, not all classes need to define destructors as virtual. Because the compiler will add a virtual function table to the class at compile time, inside to hold the virtual function pointer, if all are defined as virtual, this will increase the storage space of the class. It's wasted! do not use the base class, do not need to be imaginary! when you do not need to manipulate the object of a derived class by a pointer to a base class , the destructor for the base class should not be virtual .
Here to borrow the article code: when to use virtual destructor?
123456789101112131415161718 |
class ClxBase
{
public
:
ClxBase() {};
virtual ~ClxBase() {};
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; };
};
代码
ClxBase *pTest =
new ClxDerived;
pTest->DoSomething();
delete pTest;
|
The normal situation should be output:
12 |
Do something in class ClxDerived! Output from the destructor of class ClxDerived! |
If you define a destructor for a class clxbase as non-virtual (remove the previous virtual), the output is:
1 |
Do something in class ClxDerived! |
There is no destructor to call clxderived Oh ~ ~ ~
Also, when do you want to use a virtual destructor? , a question was raised:
Why is it dangerous to inherit a class that does not have a virtual destructor?
This question is actually explained above already, will cause the deletion not to finish! Memory leak issues. When you have a public inheritance that creates a related class that inherits from a base class, pointing to the new class object needles and references actually point to the object of origin. Because destructors are not virtual functions, when you delete A class like this, C + + does not call the destructor chain.
From for notes (Wiz)
C + + Learning constructor and copy control--what kind of situation requires virtual destructor