Detailed resolution of overloading overwriting and hiding of member functions

  • 2020-04-02 01:41:50
  • OfStack

1 overloading and overwriting
Feature of overloaded member function:
(1) same scope (in the same class);
(2) the function name is the same;
(3) different parameters;
(4) virtual keywords are optional.
Overwrite refers to the derived class function overwrite the base class function, the characteristics are:
(1) different scope (respectively in derived class and base class);
(2) the function name is the same;
(3) the parameters are the same;
(4) the base class function must have a virtual keyword.
In the following example, the functions Base::f(int) and Base::f(float) are overloaded with each other, while Base::g(void) is overwritten by the Derived::g(void).


#include <iostream.h>
class Base
{
public:
void f(int x){ cout << "Base::f(int) " << x << endl; }
void f(float x){ cout << "Base::f(float) " << x << endl; }
virtual void g(void){ cout << "Base::g(void)" << endl;}
};
class Derived : public Base
{
public:
virtual void g(void){ cout << "Derived::g(void)" << endl;}
};
void main(void)
{
Derived d;
Base *pb = &d;
pb->f(42); // Base::f(int) 42
pb->f(3.14f); // Base::f(float) 3.14
pb->g(); // Derived::g(void)
}

2. Confusing hiding rules
It wasn't difficult to distinguish between overloading and overwriting, but C++ 's hidden rules dramatically increase the complexity of the problem.
Here, "hidden" means that the functions of derived classes mask the functions of the base class with the same name. The rule is as follows:

(1) if the function of the derived class is the same as the function of the base class, but the parameters are different. At this point, the functions of the base class are hidden with or without the virtual keyword (be careful not to be confused with overloading).

(2) if the function of the derived class is the same as the function of the base class and the parameters are the same, but the base class function does not have a virtual keyword. At this point, the functions of the base class are hidden (be careful not to be confused with overrides).

In the following example:
(1) the function Derived::f(float) overrides Base::f(float).
(2) the function Derived::g(int) hides Base::g(float) instead of overloading.
(3) the function Derived::h(float) hides Base::h(float) instead of overwriting.


#include <iostream.h>
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; }
};

According to the authors, many C++ programmers don't realize that there is such a thing as "hiding." As a result of not being well understood, "hiding" can happen mysteriously, often with confusing results.

In the following example, bp and dp point to the same address, and the results should be the same, but they are not.


void main(void)
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3 (surprise!)
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
pd->h(3.14f); // Derived::h(float) 3.14
}

3 get out of hiding
Hiding rules causes a lot of trouble. In the following example, the statement pd- > F (10) is intended to call the function Base::f(int), but Base::f(int) is unfortunately hidden by Derived::f(char *). Because the number 10 cannot be implicitly converted to a string, an error occurred at compile time.

class Base
{
public:
void f(int x);
};
class Derived : public Base
{
public:
void f(char *str);
};
void Test(void)
{
Derived *pd = new Derived;
pd->f(10); // error
}


Related articles: