[TOC]

The concepts of inheritance and overloading are familiar to a C++ programmer, and so are hiding and overwriting. However, when we write a function that we think is overloaded and it returns an error, suspicion is rekindled. When a derived class inherits a function with the same name from a base class, it can be hidden, overridden, or overridden.

inheritance

A basic understanding

Inheritance is a fundamental concept of object-oriented programming (along with data abstraction and dynamic binding), and many of the rules, such as modifiers, need to be understood from the ground up: derived classes inherit members of the base class. In order to avoid unnecessary trouble, we used public inheritance in the test code.

Storage structure

It is helpful to look at the storage structure below.

  • Base classes and derived classes have their own scopes, and you’ll often see the statement that derived classes make copies of the members of their parent classes.

code

Here’s a simple example:

#include 
using namespace std;

class Base{
        int a;
        int b;
};

class Derived : public Base{
        int b;
        int c;
};


class Base1{
private:
        int a;
        int b;
};

class Derived1 : private Base1{
        int b;
        int c;
};

int main()
{
        cout << "sizeof Derived: " << sizeof(Derived) << endl;          // 16
        cout << "sizeof Base: " << sizeof(Base) << endl;                // 8
        cout << "sizeof Derived1: " << sizeof(Derived1) << endl;        // 16
        cout << "sizeof Base1: " << sizeof(Base1) << endl;              // 8

        getchar();
        return 0;
}
Copy the code

  • Derived classes, whether public or private, are 16 bytes, indicating that they have been copied. It simply says that private inheritance cannot access the private member of the base class.

hidden

You can also understand that members of a derived class with the same name hide members of the base class by looking at the storage structure diagram and remembering the rule that local variables hide global variables. Also, you can call base class member functions using the display call method. For example: d.case ::b and d.case ::fBase()

Note: Hiding and overloading can sometimes be confused here! Two points in the summary can be used to help distinguish.

code

Hidden test code:

class Base{ public: int a; int b; void fBase(){cout << "Base class function fBase()" << endl; }}; class Derived : public Base{ public: int b; int c; void fDerived() {cout << "Derived class function fDerived()" << endl; } void fBase() { cout << "Derived class function fBase()" << endl; }}; int main() { Derived d; cout << d.c << endl; cout << d.b << endl; cout << d.Base::b << endl; d.fDerived(); d.fBase(); d.Base::fBase(); getchar(); return 0; }Copy the code

  • For scopes, the C++ primer has the following description:

Derived class members mask base class members in derived class scope. Base class members are masked even if the function prototype is different.

  • In addition, the reason why function prototypes are different is compiler related.

Name lookups occur at compile time. Once the name is found in the subclass, the search is stopped. (Why don’t you keep looking? Solving the problem)

overloading

Like any other function, member functions (virtual or non-virtual) can be overloaded. Derived classes can redefine zero or more versions of all inheritance. From the previous coverage we can get the following considerations:

  • If the derived class redefines overloaded members, only those members defined in the derived class can be accessed through derived types.
  • If a derived class wants to use all of the overloaded versions through its own type, the derived type must either redefine all or none of the overloaded versions.

code

Test code:

class Base{ public: int a; int b; void fBase(){cout << "Base class function fBase()" << endl; } void fBase(int a){cout << "Base class function fBase(" << a << ")." << endl; }}; class Derived : public Base{ public: int b; int c; void fDerived() {cout << "Derived class function fDerived()" << endl; } void fBase() { cout << "Derived class function fBase()" << endl; }}; int main() { Derived d; d.fBase(); //d.fBase(2); //error: no matching function for call to 'Derived::fBase(int)' d.Base::fBase(3); getchar(); return 0; }Copy the code

	error: no matching function for call to 'Derived::fBase(int)'
Copy the code

  • One solution is to declare base class functions in derived classes without having to redefine all versions of overloaded functions

Code:

class Derived : public Base{ public: using Base::fBase; int b; int c; void fDerived() {cout << "Derived class function fDerived()" << endl; } void fBase() { cout << "Derived class function fBase()" << endl; }};Copy the code

Inaccessible “error: ‘void Base::fBase(int)’ is inaccessible”

cover

Coverage occurs under two conditions:

  • Only in the case of virtual functions
  • And the member function types of the base and derived classes must be identical, that is, the parameters and return types must be the same

Therefore, when a derived object is called, a member function of the derived class is called. However, it is also possible to call a member function of the parent class with the same name through the display. Change the above example fBase() function to a virtual function with the virtual keyword, and the result is the same [1].

virtual void fBase(){cout << "Base class function fBase()" << endl; }Copy the code

Results:

Derived class function fBase()
Base class function fBase(2).
Base class function fBase(3).
Copy the code

conclusion

  • A derived class makes a copy of all the members of the base class and stores them in different domains.
  • Overloading is under the same scope; base classes and derived classes are not in the same domain and are hidden.
  • Overlay is actually a kind of hiding, but the meaning is different.

reference

[1]C++ parent class inheritance hiding, overwriting, overloading