To understand how virtual functions work in C + +, you need to answer four questions.
1, what is a virtual function.
A virtual function is also called a virtual method because it must be a function declared in the class. All member functions starting with the virtual modifier become virtual methods. Note that the member function of the virtual decoration is not a member function name of the virtual decoration.
For example: The base class defines:
virtual void show (); virtual function as a result of virtual decoration
voidshow (int); Although it has the same name as the show virtual function declared earlier, it is not a virtual function.
All virtual function addresses are placed in the virtual function table VTBL of the owning class. In addition, a member method declared as a virtual function in the base class is still a virtual function when the subclass is reached, even though the subclass is not used with virtual adornments when the base class virtual function is redefined, the function address is still placed in the virtual function table Vtbl of the subclass.
2. Correctly distinguish between overloading, rewriting, and hiding.
Note the scope of the three concepts: functions that are in the same class will appear overloaded. Functions that are in parent classes and subclasses appear overridden and hidden.
Overload: In the same class, the function name is the same, but the argument list is different.
Overrides: In a parent-child class, the function name is the same, the argument list is the same, and there is virtual decoration.
Hidden: In a parent-child class, the function name is the same, the argument list is the same, but there is no virtual modification;
Or: The function name is the same, and the argument list is different, regardless of whether the virtual decoration is hidden.
For example:
Base class: (1) virtual void Show (); is a virtual function
(2) void show (int); Not a virtual function
Subclass: (3) void Show (); is a virtual function
(4) void show (int); Not a virtual function
1,2 constitute overloads, 3,4 constitute overloads, 1,3 constitute overrides, 2,4 constitute concealment. Another 2, 3 will also constitute a hidden, the subclass object cannot access the void Show (int) member method of the base class, but because the existence of 4 in the subclass causes the subclass object to call the void Show (int) function directly, the function invoked at this time is not a void show defined in the base class ( int) function 2, but the 3 overloaded 4th function in subclasses.
3, the virtual function table is how to create and inherit.
The creation of a virtual function table for a base class: First Find all the virtual functions in the base class declaration, encode 0,1,2,3,4 in their order of declaration ..., and then create a virtual function table for the base class in this order of declaration, which is the function pointer to these virtual functions. The addresses of these virtual functions are filled in the virtual function table in the order of the virtual function declarations. For example, if show is placed in the second position of a virtual function declaration, it is also placed in the second position in the virtual function table.
For a virtual function table for subclasses: first copy the virtual function table of the base class into the virtual function table of the subclass. If the subclass overrides the virtual function show of the base class, the function address of the show in the virtual function table of the subclass (the function address of the show virtual function of the subclass is stored before the rewrite) is updated to the function pointer of the overridden function. If subclasses add declarations of virtual functions, add the addresses of these virtual functions to the back of the class virtual function table.
4, the virtual function table is how to access.
When executing pbase->show (), observe whether show is declaring virtual or non-virtual functions in the base base class. If a virtual function uses a dynamic binder (which uses a virtual function table to determine how to call a function), a static binder is used for a non-virtual function (depending on the type of the call pointer pbase to determine which class's member function is invoked). Let's assume that show is a virtual function, first of all: because checking to the PBase pointer type refers to the class base of show defined as a virtual function, so find the object that PBase refers to (possibly base type or extend type.) To access the object to get the virtual function table address of the class to which the object belongs. Second: Find the bit order of the position declared in the base class in all the virtual function declarations in the base class. The function pointer that accesses the order in the virtual function table of the object to which PBase refers (possibly extend, polymorphism) is then obtained to perform the function.
For example:
Base class Base::virtualvoid Show (); (1)
Sub-class Extend::virtualvoid show (); (2)
Externext;
base*pbase=&ext;
Pbase->show ();
When executing pbase->show (), view Show () first into base, discover it as a virtual function, then access the Ext object that pbase points to, get the virtual function table of the Extend class in the object, and find the bit order 0 of the Show () declaration in the base class declaration, Access the virtual function table of the extend class at 0, get the function address of show. Note If only the base class defines virtual void show (), and the subclass does not override virtual void show (), which is the above function (2), the address stored in the bit order 0 in the Extend virtual function table is still the virtual void defined in the base class Show () function, and if the virtual void Show () method in the base class is overridden in the Extend class, the function address of the bit order 0 in the Extend virtual function table is updated to the newly overridden function address in extend. This will result in polymorphic behavior when calling Pbase->show ().
Summary: When Pbase->show () is invoked, the steps performed:
1, determine if show in the base class is a virtual function.
2, if not a virtual function, locate the class base of the object to which the pbase points. Execute Base::show (). If the virtual function executes step 3.
3, accessing the virtual function table pointer of the object referred to in pbase gets the virtual function table of the class of PBase object.
4, look for show in base () in the declaration of the bit Order X, to step 3 in the virtual function table found in the bit order 3, so that the show to execute the function address.
5, access the function that the address points to based on the function address and the function type (formal parameter and return value) of show that is declared in base.
The above is the working mechanism of the virtual function.
Note that only the member methods that are decorated with virtual are placed in the virtual function table.
The shadowing of a subclass of a parent function will result in the inability to access the member method of the base class through the subclass object.
Therefore, the following recommendations are given:
1. To redefine the method of the parent class in a subclass (with virtual as an override and no virtual to hide), you should ensure that the function declaration in the subclass is exactly the same as the formal parameter in the parent class function declaration. However, the return value type is the reference/pointer of the base class reference/pointer (the return value covariant) that can return a subclass when it is redefined, because the object of the subclass can be assigned to the base class reference/pointer.
2, the overloaded version of the function is declared in the Jocky class, and the overloaded versions of all base classes should be redefined when redefined in the derived class. This is because, by redefining a function, other overloaded versions of the base class are hidden, causing subclasses to not use the member methods of those base classes. So you need to redefine each. If some of the overloaded versions of the parent class do not need to be modified, the member methods of the base class are called directly in the definition body (using Action for qualifier access), because an overloaded version is redefined, even if some overloaded versions need not be modified.
3, from the virtual function of the implementation mechanism can be seen in subclasses to achieve polymorphism needs to meet three important conditions. (1) The function is declared as a virtual function in the base class. (2) in subclasses, the virtual functions of the base class are overridden. (3) The pointer to the base class points to the object of the subclass