The relationship between C + + constructors, destructors, and virtual functions
1. If we define a constructor, the compiler will no longer generate a default constructor for us.
2. Compiler-generated destructors are non-virtual, except for a subclass whose parent class has a virtual destructor, at which point the function virtual attribute comes from the parent class.
3. Classes with virtual functions can almost be determined to have a virtual destructor.
4. If a class cannot be a base class, do not declare that the destructor is a virtual function, and the virtual function is space-consuming.
5. An abnormal exit of a destructor causes incomplete destruction and thus a memory leak. It is best to provide a management class that provides a way to deconstruct in the management class, and the caller then decides what to do next, based on the results of this method.
6. Do not call virtual functions in the constructor function. In the construction of a base class, a virtual function is non-virtual and does not go into a derived class, and is both a static binding used. It is obvious that when we construct an object of a subclass, we call the constructor of the base class first, construct the base class part of the subclass, the subclass is not constructed yet, it is not initialized, if you call a virtual function in the construction of the base class, it is dangerous to call an object that has not been initialized, so C + + It is not possible to invoke the virtual function implementation of a subclass when constructing the part of the parent class object. But not that you can not write the program, you write this, the compiler will not error. It's just that if you write this, the compiler will not give you an implementation of the subclass, but rather call the implementation of the base class.
7.
do not call virtual functions in destructors. At the time of the destructor, the destructor of the subclass is called first, then the subclass part of the object is reconstructed, and then the destructor of the base class is called, and if the virtual function is called in the destructor of the base class, it is very dangerous to call the function inside the sub-class object that has been refactored.
8. Remember that when writing a copy function of a derived class, the copy function of the base class is called to copy the part of the base class, and it cannot be forgotten.
the relationship between constructors, destructors and virtual functions
1. Why can't a constructor be a virtual function?
Because, from the point of use, a virtual function invokes a member of a derived class through a base-class pointer or reference, the object must exist before the call, and the constructor is created to create the object.
2. Why destructors in derived classes are often virtual destructors
Note that the default is not a destructor
In a word, to avoid a memory leak
If you do not consider the state of a virtual function, give a base class and a derived class, if you call a destructor for a derived class, you will definitely throw a destructor that calls the base class, and it doesn't matter if the destructor is not a virtual function.
Now consider the problem of virtual functions, because using virtual functions allows us to define a base class pointer or reference that can operate directly on a derived class, there are two cases:
If you do not set the destructor of a base class to a virtual function, when you delete the object, the system can only call the base class destructor if you delete the base class pointer directly, instead of invoking the derived class constructor. This can lead to memory leaks.
If you set the destructor of a base class to a virtual function, deleting the object directly deletes the base class pointer, and the system invokes the derived class destructor, which causes the system to automatically invoke its own base class, which does not cause a memory leak.
Therefore, when writing a class, try to set its destructor to virtual function, but the destructor is not a virtual function by default.
Example one: Removing a derived class object from a derived class pointer
1#include <iostream>2 using namespacestd; 3 4 classBase5 { 6 Public: 7~Base ()8 { 9cout<<"destructor for Base"<<Endl; Ten } One A }; - - classDerive: PublicBase the { - Public: -~Derive () - { +cout<<"the destructor of Derive"<<Endl; - } + A }; at - voidMain () - { -derive* p =NewDerive (); - Deletep; -System"Pause"); in}
Results:
Parse: Call the destructor of the base class and call the destructor of the derived class
Description
(1) P is a pointer to a derived class derive, and when you delete P, the destructor for derive is automatically called, and after that, there is a destructor that continues to invoke the base class base.
(2) This procedure has no relation to the virtual function, so long as the destructor of the derived class is called, the destructor of its ancestor is automatically called back.
Example two: When removing a derived class object from a base class pointer without setting the destructor of the base class to a virtual function
1#include <iostream>2 using namespacestd; 3 4 classBase5 { 6 Public: 7~Base ()8 { 9cout<<"destructor for Base"<<Endl; Ten } One A }; - - classDerive: PublicBase the { - Public: -~Derive () - { +cout<<"the destructor of Derive"<<Endl; - } + A }; at - voidMain () - { -base* p =NewDerive (); - Deletep; -System"Pause"); in}
Results:
Analysis: Only the destructor of the base class was called, and the destructor of the derived class was not called
Description
(1) Since p is a pointer to base class base, and the destructor of its base is not a virtual function, when P is removed, the destructor of base is called directly, instead of the destructor that actually points to derive (this is used to compare with the later), If there is memory release in the destructor in derive, a memory leak is caused.
Example three: When you delete a derived class object from a base class pointer and set the destructor of the base class to a virtual function
1#include <iostream>2 using namespacestd; 3 4 classBase5 { 6 Public: 7 Virtual~Base ()8 { 9cout<<"destructor for Base"<<Endl; Ten } One A }; - - classDerive: PublicBase the { - Public: -~Derive () - { +cout<<"the destructor of Derive"<<Endl; - } + A }; at - voidMain () - { -base* p =NewDerive (); - Deletep; -System"Pause"); in}
Results
Analysis
(1) Since p is a pointer to a derived class base, and its destructor is a virtual function, due to the nature of the virtual function, the derive destructor is called directly when P is removed.
(2) After calling derive's destructor, a call to the destructor of the base class base of derive is raised. It doesn't matter if it's a virtual function, it's just the destructor's own function.
In summary, in a collection of classes with derived existence, the destructor of the base class is set as virtual function as possible, and is often a virtual function, but the default is not a virtual function, and it does not need to be set to a virtual function.
Note: If the destructor of the base class is set to a virtual function, all derived classes are also default to the virtual destructor, even if there is no keyword virtual.
In a base class, what is the reason why the destructor is set to a virtual destructor?
This is mainly because:
(1) When you need to manipulate a derived class using a pointer to a base class, it is possible to cause a memory leak. If you do not need to do this, you can not set it completely.
(2) When the destructor of a base class is set to a virtual function, its destructor derived from the class is automatically a virtual function.
3, all the class of destructors are set to virtual function OK?
Certainly not good, in fact this is to ask the virtual function of the shortcomings.
Virtual functions are handled at run time, in order to invoke different virtual functions based on different objects at run time, which requires that classes with virtual functions have some extra information that is used at run time to determine which virtual function the object should call. The system stores a virtual function table VTBL (virtual table) for each object. A virtual function table is an array of function pointers, each of which contains a virtual function and stores the table's first address in vptr (virtual table pointer). When an object calls a virtual function, the actual called function is determined by the following steps: Locate the VTBL that the object vptr points to, and then look for the appropriate function pointer in VTBL.
Therefore, a class object that uses a virtual function takes up more space than a class object that does not use a virtual function, and there is a time cost to find out which virtual function to use . That is, when a class is not intended to be a base class, it is not necessary to set the function as a virtual function.
To the relationship between C + + constructors, destructors, and virtual functions