Hide C ++ functions (function names are the same)

Source: Internet
Author: User

I read Lin Rui's high-quality programming guide 8.2.2 confusing hidden rules. (here, the hidden function of the derived class shields the base class functions with the same name)

 

This section is well written: 1. List the hidden situations.

2. The example is very relevant, so that you can better understand it.

3. Understanding of hidden functions.

4. Propose corresponding solutions.

  • If the function of the derived class has the same name as the function of the base class, but the parameters are different, the function of the base class will be hidden (do not confuse the function with the overload) regardless of whether there is a virtual keyword ).
  • If the function of the derived class has the same name as the function of the base class, and the parameters are the same, but the base class function does not have the virtual keyword, the base class function is hidden (do not confuse with overwrite ).

The above two situations cause function hiding. Read the example in the book:

 

# Include <iostream>
Using namespace STD;
Class base
{
Public:
Virtual void F (float X) {cout <"base: F (float)" <x <Endl ;}
Void g (float X) {cout <"base: G (float)" <x <Endl ;}
Void H (float X) {cout <"base: H (float)" <x <Endl ;}
};

 

Class derived: public Base
{
Public:
Virtual void F (float X) {cout <"derived: F (float)" <x <Endl ;}
Void g (int x) {cout <"derived: G (INT)" <x <Endl ;}
Void H (float X) {cout <"derived: H (float)" <x <Endl ;}
};

 

Int main ()
{
Derived D;
Base * pb = & D;
Derived * Pd = & D;

// No hiding
Pb-> F (3.14f); // derived: F (float) 3.14
Pd-> F (3.14f); // derived: F (float) 3.14

// Case 1
Pb-> G (3.14f); // base: G (float) 3.14
Pd-> G (3.14f); // derived: G (INT) 3 (surprise !)

// Hide case 2
Pb-> H (3.14f); // base: H (float) 3.14 (surprise !)
Pd-> H (3.14f); // derived: H (float) 3.14

System ("pause ");
Return 0;
}

 

  • If the function of the derived class has the same name as the function of the base class, and the parameters are the same, but the base class function does not have the virtual keyword, the base class function is hidden (do not confuse with overwrite ).

// Hide
Pb-> H (3.14f); // base: H (float) 3.14 (surprise !)
Pd-> H (3.14f); // derived: H (float) 3.14

 

Personal Opinion:

 

If you have learned Java polymorphism, this result should be difficult to accept.

 

If the derived Object D is implicitly converted to the base object, the function with the same name as the derived Object D is overwritten by the derived Object D. Therefore, the execution results of the two objects are the same.

 

But here is C ++, not Java. for C ++, if a function of the base class does not have the virtual keyword, it has nothing to do with the same name function (the same parameter) of the derived class.

 

For details, see "key concepts: Name Search and inheritance" On page 501 of C ++ primer ".

 

PB is a base pointer and Pb pointer is bound to the derived Object D. However, since the H (float) function of the base class is not a virtual function, the base is executed no matter what type of the actual object is :: H (float ).

 

The program will directly look for the H function in the base class; if there is no H function, it will look for the H function in its parent class; If the H function is still not found, it will go to the upper class of its parent class to continue searching for the H function; and so on until method A is found; if it is not found in the end, your program cannot be compiled! (This search method is the same as Java)

 

Java functions do not have the virtual keyword, but the derived class and the base class are overwritten as long as the function name and parameter are the same. if you think about it in turn, isn't every Java function a virtual function compared to C ++? Maybe C ++ is about efficiency. I don't want all functions to use dynamic concatenation.

 

  • If the function of the derived class has the same name as the function of the base class, but the parameters are different, the function of the base class will be hidden (do not confuse the function with the overload) regardless of whether there is a virtual keyword ).

// Case 1
Pb-> G (3.14f); // base: G (float) 3.14
Pd-> G (3.14f); // derived: G (INT) 3 (surprise !)

 

Personal Opinion: 

 

In fact, this cannot be said to be hidden because g (float) and g (INT) are different functions. After C ++ is compiled, the names in the symbol library are _ g_float and _ g_int. even if they all have virtual keywords, there is a different function from the derived class and the base class, so there is no overwrite relationship (overload is not possible ).

 

PB is a base pointer, and Pb pointer is bound to the derived Object D. The base class does not have a G (INT) function at all. Therefore, the PD pointer cannot always call derived: G (INT) function.

 

Pb-> G (3.14f); the program finds the matched function base: G (float) in the base class, and then calls this function.

 

Pd-> G (3.14f); // derived: G (INT) 3 (surprise !)

Compile a function that matches g (3.14f) in the derived class first. It finds g (INT) and only one function in the derived class matches. even if G (INT) is virtual, the G (INT) function of the derived object d pointed to by the PD pointer is the same as the G (INT) function of the derived class, all the calls are the derived: G (INT) function, so there is no polymorphism and no need for Dynamic Association. (For conditions for dynamic Association, see section C ++ primer 15.2.4 "virtual and other member functions". Here, dynamic association is not required, because it does not meet the second condition of Dynamic Association ).

 

Even if the base class has a matching function virtual g (float X), virtual g (float X) is a virtual function table (virtual function table, vtbl, in plus 13.4.4), if dynamic association is not performed, the program will not search for the corresponding function address in vtbl, and the function address in vtbl will not be referenced and will not be called.

Therefore, if the G (float X) of the base class is added with the virtual keyword, the result will not change. If the G (INT) of the derived class is added with the virtual keyword, the result will remain unchanged.

 

If the derived class adds a function virtual void g (float X) {cout <"derived: G (float)" <x <Endl ;}, add the G (float X) of the base class to the virtual keyword.

 

The result is

Pb-> G (3.14f); // derived: G (float) 3.14
Pd-> G (3.14f); // derived: G (float) 3.14

 

Pb-> G (3.14f)

 

PB is a base pointer, and Pb pointer is bound to the derived Object D. because the G (float) function of the base class is virtual and the base class pointer calls the G (float) function, the static type of the Object D bound to the Pb pointer is the derived class, the G (float) function of the derived class is also virtual. Generally, the dynamic type of the object can be determined only when the program is running. therefore, the compiler uses dynamic concatenation for the virtual function g (float.

 

Because the derived class provides a new definition of the virtual function g (float), the address of the G (float) function in the virtual function table (vtbl) of the derived Object D is saved as derived :: the address of the G (float) function. when the Pb pointer calls the virtual function g (float), the program searches for the address of the G (float) function in the virtual function table (vtbl) of the derived Object D, then execute the function of this address. therefore, Pb-> G (3.14f) executes the derived: G (float) function.

 

 

 

 

 

 

Speaking of this, it is really troublesome for the subclass to reload the method of the parent class. Is it necessary to copy all the methods? In fact, it is not necessary. If a subclass object can implicitly convert the parent class object, but its own method does not exist for the base class object, of course, these methods cannot be called for base class objects. therefore, the subclass does not need to overload the method of the parent class. It is better to create a method of its own!

 

The virtual keyword, as if to tell you that this function can overwrite the function with the same name and parameter in the derived class. The pure virtual function directly tells the derived class, you must write a function with the same name and parameter to overwrite me. Haha!

 

Important exam: "key concepts: Polymorphism in C ++" On page 480th of C ++ primer ".

C ++ primer plus 13.4.4 virtual member functions and dynamic concatenation.

Page 449th of "C ++ primer plus": How virtual functions work ".

C ++ primer 15.2.4 virtual and other member functions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.