Reference: http://www.weixueyuan.net/view/6375.html
Summarize:
The function signature includes the number, order, and parameter data types of the function names and functions parameters.
It is important to note that the function signature does not contain the function return value part, if the two function only has the function return value to be different, then the system cannot distinguish these two functions, at this time the compiler prompts the syntax error.
Function overloading means that two functions have the same function name, but the number of function arguments or the parameter types are different. Function overloading occurs between top-level functions or in the same class, and function overloading does not need to form an inheritance relationship.
A function overload is a compile-time binding, and it is not polymorphic.
The conditions of covering and polymorphism are the same, and coverage is the representation relationship between functions, and Polymorphism describes a property of a function, which is actually the same grammatical phenomenon.
Overrides first require an inheritance relationship, followed by a member function that requires the same function signature in the two classes that make up the inheritance relationship, and the two member functions must be virtual member functions, with these two conditions, the virtual member function in the derived class overrides the virtual member function with the same name in the base class. If we call a virtual member function through a base-class pointer or reference, polymorphism is formed.
Function overrides are run-time bound, but be aware that if a function is not a virtual function, the function is bound to compile-time regardless of what method is called.
Function shadowing also requires a function of the same function name in the two classes that make up the inheritance relationship, and if the two functions are not enough to cover the relationship, the masking relationship is formed. (Note that it is not the same function signature, only the same function name is required)
overriding requires the same function signature, and shadowing requires only the same function name.
In general, the same function name is usually used in the following cases:
- function overloading of the top-level function. For program designers, the use of function overloading is a great convenience when implementing functions that are functionally identical but have different types of data being processed. For example, it is convenient to design an absolute value function that is designed for integer and double types and an ABS function that does not require attention to the parameter type.
- Overload of member functions in a class, this function overload and top-level function overloading can also be convenient for our programs.
- class, design multiple constructors for different ways of initializing objects.
- The same function signature is used in the inheritance hierarchy in order to use polymorphic attributes.
In addition to the same function name also causes the function to be obscured in the inheritance hierarchy, which often makes the program difficult to understand, so it is recommended to use the function masking mechanism with caution .
------------------------------------
A polymorphic function is a function that binds the function entry address to the function name at run time, and only the virtual function is polymorphic. But in addition to virtual functions, overloading and masking also have the same function name characteristics, here to make a distinction. To illustrate the convenience, we introduce the concept of function signature. The function signature includes the number, order, and parameter data types of the function names and functions parameters.
Example 1:
void f () void g () void f (int)
Example 2:
void int )void F (double)
Example 3:
void F (doubleint)void f (intdouble)
To understand the meaning of the function signature, let's take a look at the three examples above. In Example 1, the function f () and function g () are different, so the function signatures of the two functions are different, the F () function and the f (int) function have parameters, one has no parameters, the function signature is also different, the G () function and f (int) function functions are different and the number of function parameters is different. Therefore, the function signatures of these two functions are also different. In Example 2, the two function functions have the same name, the function parameters are the same, but the function arguments are of different types, so the function signatures of the two functions are not the same. Example 3 in two functions, the function name is the same, function parameter number is the same, the function parameter type is the same, is a double type and an int type, but the function parameter order is not the same, so that the function signature of the two functions is also different.
It is important to note that the function signature does not contain the function return value part, if the two function only has the function return value to be different, then the system cannot distinguish these two functions, at this time the compiler prompts the syntax error.
Example 4:
int f (intdouble)void f (intdouble)
In this case, the function names of the two functions are the same, the function parameters are the same, the function parameter types are the same, and the function parameters are the same, so that the function signatures of the two functions are the same. However, the return value of the two functions is different, the compiler cannot distinguish between the two functions by simply returning the value of the function, and the compiler hints at the syntax error.
After understanding the meaning of the function signature, let's look at overloading, overwriting, and shadowing.
1) Heavy Duty
function overloading means that two functions have the same function name, but the number of function arguments or the parameter types are different. function overloading occurs between top-level functions or in the same class, and function overloading does not need to form an inheritance relationship.
Example 5:
class Base{ Public : Base(); Base(inta); Base(intAintb); Base(Base&); intFuninta); intFunDoublea); intFunintAintb);Private: intx; inty;};intGinta);intGDoublea);intGintAintb);
In this example, we have listed several function overloading scenarios. The first is the constructor overload of the function, we declare four constructors in the class, these four functions make up the overloaded relationship, the first three functions are only different from the number of function arguments, the fourth constructor is a copy constructor, which is different from the previous default constructor and two parameters of the parameter constructor. A member function in a class can also be overloaded, such as the three fun functions of the base class in this example. These two cases are function overloads inside the class, and the top-level function in the class can also be overloaded with functions, such as the G function in this example, which is the top-level function, because the function name is the same, but the function parameters are different, which make up the function overloading relationship.
A function overload is a compile-time binding, and it is not polymorphic.
2) Coverage
The conditions of covering and polymorphism are the same , and coverage is the representation relationship between functions, and Polymorphism describes a property of a function, which is actually the same grammatical phenomenon.
Overrides first require an inheritance relationship, followed by a member function that requires the same function signature in the two classes that make up the inheritance relationship, and the two member functions must be virtual member functions, with these two conditions, the virtual member function in the derived class overrides the virtual member function with the same name in the base class. If we call a virtual member function through a base-class pointer or reference, polymorphism is formed.
Example 6:
#include <iostream>using namespacestd;class Base{ Public : Virtual voidVir1 () {}Virtual voidVir2 () {}};classDerived: Public Base{ Public: voidVir1 () {}voidVir2 () {}};intMain () {Base*p; P=Newderived; P-Vir1 (); P-Vir2 (); Deletep; return 0;}
This example is a very simple polymorphic sample program where the base class and the derived class form an inheritance relationship in which the member functions Vir1 and VIR2 have the same name, and both functions of the same name are declared for virtual functions. As a result, the function overrides are covered, and the VIR1 function in the derived class overrides the Vir1 function in the base class, and the Vir2 function in the derived class overrides the Vir2 function in the base class. The Vir1 and VIR2 virtual functions are called by the base-class pointers in the main function, which form a polymorphic state, and the functions run as run-time bindings.
function overrides are run-time bound, but be aware that if a function is not a virtual function, the function is bound to compile-time regardless of what method is called. If we remove the two virtual keywords from the base class in example 6, then calling the Vir1 and VIR2 functions in the main function is a compile-time binding, regardless of whether P is pointing to a derived class object or a base class object, the execution will be the VIR1 and VIR2 functions of the base class.
3) Masking
function Shadowing also requires a function of the same function name in the two classes that make up the inheritance relationship, and if the two functions are not enough to cover the relationship, the masking relationship is formed. masking is easy to understand, as long as the derived class has the same function name as the base class (note that it is not the same function signature, only the same function name is required ) and does not constitute an overwrite relationship is obscured.
Shadowing can be divided into two cases, one between non-virtual functions and the other between virtual functions. We introduce the two masking cases separately through the program examples.
Example 7:
#include <iostream>using namespacestd;class Base{ Public : voidVir1 () {cout<<"Base Vir1"<<Endl;} voidVir2 () {cout<<"Base Vir2"<<Endl;}};classDerived: Public Base{ Public: voidVir1 () {cout<<"derived Vir1"<<Endl;} voidVir2 (int) {cout<<"derived Vir2"<<Endl;}};intMain () {Base*p; P=Newderived; P-Vir1 (); P-Vir2 (); Deletep; Derived D; D.vir1 (); D.vir2 (5); D.Base:: Vir1 (); D.Base:: Vir2 (); return 0;}
In this case, there is no virtual function, and the base class and the derived class form an inheritance relationship, because the two classes that make up the inheritance relationship have the same name function, thus constituting a function mask. The Vir1 function in a derived class obscures the VIR1 function in the base class, and the Vir2 function in the derived class obscures the VIR1 function in the base class. It is important to note that although the VIR2 function in the derived class differs from the function signature of the VIR2 function in the base class, it only requires the same function name to form a function mask. We then analyze the main function, in which we first define a pointer to the base class type, the pointer to the base class object, and then call the function Vir1 and vir2 through the pointer, which is called the Vir1 and VIR2 functions of the base class, because it does not form polymorphic. A derived class object, D, is then defined to call the VIR1 and VIR2 functions, because Vir1 and Vir2 in the derived class obscure the Vir1 and VIR2 functions in the base class, so the Vir1 and VIR2 functions in the derived class are called directly. If you need to call a function in a masked base class through a derived class object, you need to handle it through the domain resolution operator, in the last D.base::vir1 () of this example, and D.base::vir2 (). The final results of this program are as follows:
Base Vir1
Base Vir2
Derived Vir1
Derived Vir2
Base Vir1
Base Vir2
If the two classes that make up the inheritance relationship contain virtual functions with the same name, the situation is very complex, but it is still very simple to judge, or the principle: if there is no cover, it will be obscured. overriding requires the same function signature, and shadowing requires only the same function name.
Example 8:
#include <iostream>using namespacestd;class Base{ Public : Virtual voidVir1 () {cout<<"Base Vir1"<<Endl;} Virtual voidVir2 () {cout<<"Base Vir2"<<Endl;}};classDerived: Public Base{ Public: Virtual voidVir1 () {cout<<"derived Vir1"<<Endl;} Virtual voidVir2 (int) {cout<<"derived Vir2"<<Endl;}};intMain () {Base*p; P=Newderived; P-Vir1 (); P-Vir2 (); Deletep; Derived D; D.vir1 (); D.vir2 (5); D.Base:: Vir1 (); D.Base:: Vir2 (); return 0;}
In this program, two classes, the base class, and the derived class are defined, and the two classes form an inheritance relationship, and the derived class and base class contain functions with the same name, and functions with the same name are virtual functions. For these two functions of the same name, let's analyze it one by one, first of all, to look at Vir1, the function signature of the VIR1 function in the base class and the derived class is the same, and it is the virtual function, which forms the function coverage relation. Take a look at the VIR2 function, the VIR2 function in the base class and the VIR2 function in the derived class have the same name, but the function parameters are different, so their function signature is different, so the VIR1 function in the derived class does not constitute a function overlay, since the function name is the same, it can form a function mask.
Then we take a look at the main function, in the main function, we define a pointer to a base class type, pointer to the derived class object, and then call the Vir1 and VIR2 functions, respectively, through the pointer. Because Vir1 is a function overlay, the call to the VIR1 function is a vir1 function in a derived class because the Vir1 is called by the base-class pointer, because the P-pointer points to the derived class object. The VIR2 function in the derived class and the VIR2 function in the base class only constitute a function mask, so calling the Vir2 function through a base class type pointer does not form polymorphic, and ultimately calls the VIR2 function in the base class. The derived class object D is then defined, and the function called by the derived class object D can only be a function in a derived class, including, of course, a function inherited from a base class. D.vir1 () and D.vir2 (5) Both function invocation statements are called by new member functions in derived classes, although the VIR1 function in the derived class forms an overlay relationship with the VIR1 function in the base class, but is not called by a base class pointer or reference, and therefore does not constitute polymorphism, so that If you need to invoke the Vir1 function inherited from the base class through an object, the domain resolution operator is also required. The VIR2 function in the derived class and the VIR2 function in the base class are obscured, so calling through object and member selectors is still the new Vir2 function in the derived class, and if you want to call the VIR2 function in the base class, you need to resolve the operator through the domain. Example 8 program operation results are as follows:
Derived Vir1
Base Vir2
Derived Vir1
Derived Vir2
Base Vir1
Base Vir2
The above summarizes the function name of the same all cases, the function name of the same use of good can be designed to bring greater convenience for the design, the use of the bad is easy to mislead the program designers.In general, the same function name is usually used in the following cases:
- function overloading of the top-level function. For program designers, the use of function overloading is a great convenience when implementing functions that are functionally identical but have different types of data being processed. For example, it is convenient to design an absolute value function that is designed for integer and double types and an ABS function that does not require attention to the parameter type.
- Overload of member functions in a class, this function overload and top-level function overloading can also be convenient for our programs.
- class, design multiple constructors for different ways of initializing objects.
- The same function signature is used in the inheritance hierarchy in order to use polymorphic attributes.
In addition to the same function name also causes the function to be obscured in the inheritance hierarchy , which often makes the program difficult to understand, so it is recommended to use the function masking mechanism with caution.
4.5 C + + overloading, overwriting, and masking