C++ 成员函数的重载,继承,覆盖和隐藏

一、 C++成员函数的重载

C++中的成员函数有四种,分别是普通成员函数,virtual虚函数,const成员函数。

  • (1) void func(int a);
  • (2) virtual void func(int a);
  • (3) void func(int a) const;

如果在一个类中,声明这四种函数,哪是重复定义?哪些是重载?

其中(1)(2)是重复定义,故编译不能通过,而(3)与(1)(2)是不同类型的函数,是重载。

成员函数被重载的特征是:

  • (1)具有相同的作用域(即同一个类定义中);
  • (2)函数名字相同
  • (3)参数类型,顺序 或 数目不同(包括const参数和非const函数)
  • (4)virtual关键字可有可无。

从成员函数的重载特征中,可以知道(1)(2)是重复定义。那么(3)为什么和(1)(2)不同呢?

因为类中的函数,都会自动添加一个自身类指针this,所以

  1. void func(int a) ==== void func(Base * thisint a)
  2. virtual func(int a) ==== virtual func(Base *thisint a)
  3. void func(int a)const === void func(const Base *thisint a) const

所以(3)可以与(1)(2)发生重载,因为参数有一个const。

二 、C++成员函数的继承

  1. #include <iostream>
  2. using namespace std;
  3. class Base {
  4. public:
  5.     void f(int a){
  6.         cout << “Base::f(int a)” << endl;
  7.     }
  8.     virtual void g(int a) {
  9.         cout << “virtual Base::g(int a)” << endl;
  10.     }
  11. };
  12. class Derived : public Base
  13. {
  14. public:
  15.     void h(int a) {
  16.         cout << “Derivd::h(int a)” << endl;
  17.     }
  18. };
  19. int main()
  20. {
  21.     Base b;
  22.     b.f(3);
  23.     b.g(4);
  24.     Derived d;
  25.     d.f(3);
  26.     d.g(4);
  27.     d.h(3);
  28. }
  29. #include <iostream>
  30. using namespace std;
  31. class Base {
  32. public:
  33.  void f(int a){
  34.   cout << “Base::f(int a)” << endl;
  35.  }
  36.  virtual void g(int a) {
  37.   cout << “virtual Base::g(int a)” << endl;
  38.  }
  39. };
  40. class Derived : public Base
  41. {
  42. public:
  43.  void h(int a) {
  44.   cout << “Derivd::h(int a)” << endl;
  45.  }
  46. };
  47. int main()
  48. {
  49.  Base b;
  50.  b.f(3);
  51.  b.g(4);
  52.  Derived d;
  53.  d.f(3);
  54.  d.g(4);
  55.  d.h(3);
  56. }

 

Derived d的对象模型:

wkiom1hfu2zzrlitaaoj8jz7avo38-jpg

则在子类Derived d中继承了父类中的virtual void g(int a) ; void f(int a);

运行结果为:

wkiom1hfu2zxglxhaail8vqmsoi10-jpg

三、C++成员函数的覆盖

覆盖是指派生类重新实现(或者改写)了基类的成员函数,其特征是:

  • (1)不同的作用域(非别位于派生类和基类中);
  • (2)函数名称相同
  • (3)参数列表完全相同;
  • (4)基类函数必须是虚函数。

从(4)中我们得知覆盖只是针对虚函数的。

  1. #include <iostream>
  2. using namespace std;
  3. class Base {
  4. public:
  5.     void f(int a){
  6.         cout << “Base::f(int a)” << endl;
  7.     }
  8.     virtual void g(int a) {
  9.         cout << “virtual Base::g(int a)” << endl;
  10.     }
  11. };
  12. class Derived : public Base
  13. {
  14. public:
  15.     void h(int a) {
  16.         cout << “Derivd::h(int a)” << endl;
  17.     }
  18.     virtual void g(int a) {
  19.         cout << “virtual Derived::g(int a)” << endl;
  20.     }
  21. };
  22. int main()
  23. {
  24.     Base b;
  25.     b.f(3);
  26.     b.g(4);
  27.     Derived d;
  28.     d.f(3);
  29.     d.g(4);
  30.     d.h(3);
  31. }
  32. #include <iostream>
  33. using namespace std;
  34. class Base {
  35. public:
  36.  void f(int a){
  37.   cout << “Base::f(int a)” << endl;
  38.  }
  39.  virtual void g(int a) {
  40.   cout << “virtual Base::g(int a)” << endl;
  41.  }
  42. };
  43. class Derived : public Base
  44. {
  45. public:
  46.  void h(int a) {
  47.   cout << “Derivd::h(int a)” << endl;
  48.  }
  49.  virtual void g(int a) {
  50.   cout << “virtual Derived::g(int a)” << endl;
  51.  }
  52. };
  53. int main()
  54. {
  55.  Base b;
  56.  b.f(3);
  57.  b.g(4);
  58.  Derived d;
  59.  d.f(3);
  60.  d.g(4);
  61.  d.h(3);
  62. }

Derived d对象模型如下:

wkiol1hfu2zdma1aaap2vql9pac42-jpg

其中Derived中重新定义了基类的虚成员函数virtual void g(int a);

wkiol1hfu22gl1x1aapayqhpw6u65-jpg

四、C++成员函数的隐藏

隐藏是指派生类的成员函数遮蔽了与其同名的基类成员函数,具体规则如下:

(1) 派生类的函数与基类的函数同名,但是参数列表有所差异。此时,不论有无virtual关键字,基类的函数在派生类中将被隐藏。(注意别与重载混合)

(2)派生类的函数与基类的函数同名,参数列表也相同,但是基类函数没有virtual关键字。此时,基类的函数在派生类中将被吟唱。(注意别与覆盖混合)

判断下面哪些函数是覆盖,哪些函数是隐藏?

  1. #include <iostream>
  2. using namespace std;
  3. class Base {
  4. public:
  5.     virtual void f(float x) {
  6.         cout << “virtual Base::f(float) “ << x << endl;
  7.     }
  8.     void g(float x) {
  9.         cout << “Base::g(float) “ << x << endl;
  10.     }
  11.     void h(float x) {
  12.         cout << “Base::h(float) “ << x << endl;
  13.     }
  14. };
  15. class Derived : public Base{
  16. public:
  17.     virtual void f(float x) {
  18.         cout << “virtual Derived::f(float) “ << x << endl;
  19.     }
  20.     void g(int x) {
  21.         cout << “Derived::g(int) “ << x << endl;
  22.     }
  23.     void h(float x) {
  24.         cout << “Derived::h(float) “ << x << endl;
  25.     }
  26. };
  27. int main(void)
  28. {
  29.     Derived d;
  30.     Base *pb = &d;
  31.     Derived *pd = &d;
  32.     pb->f(3.14f);
  33.     pd->f(3.14f);
  34.     pb->g(3.14f);
  35.     pd->g(3.14f);
  36.     pb->h(3.14f);
  37.     pd->h(3.14f);
  38. }
  39. #include <iostream>
  40. using namespace std;
  41. class Base {
  42. public:
  43.  virtual void f(float x) {
  44.   cout << “virtual Base::f(float) “ << x << endl;
  45.  }
  46.  void g(float x) {
  47.   cout << “Base::g(float) “ << x << endl;
  48.  }
  49.  void h(float x) {
  50.   cout << “Base::h(float) “ << x << endl;
  51.  }
  52. };
  53. class Derived : public Base{
  54. public:
  55.  virtual void f(float x) {
  56.   cout << “virtual Derived::f(float) “ << x << endl;
  57.  }
  58.  void g(int x) {
  59.   cout << “Derived::g(int) “ << x << endl;
  60.  }
  61.  void h(float x) {
  62.   cout << “Derived::h(float) “ << x << endl;
  63.  }
  64. };
  65. int main(void)
  66. {
  67.  Derived d;
  68.  Base *pb = &d;
  69.  Derived *pd = &d;
  70.  pb->f(3.14f);
  71.  pd->f(3.14f);
  72.  pb->g(3.14f);
  73.  pd->g(3.14f);
  74.  pb->h(3.14f);
  75.  pd->h(3.14f);
  76. }

其中子类Derived中 vitual void f(float x)  是覆盖,而void g(int x) 和void h(float x)都是隐藏。

运行结果:

wkiom1hfu22t-c5xaalsduxai4869-jpg

再看一个例子:

  1. #include <iostream>
  2. using namespace std;
  3. class Base
  4. {
  5. public:
  6.     virtual void f(int a) {
  7.         cout << “virtual Base::f(int a)” << endl;
  8.     }
  9.     void f(double d) {
  10.         cout << “Base::f(double d)” << endl;
  11.     }
  12. };
  13. class Derived : public Base
  14. {
  15. public:
  16.     void f(double d) {
  17.         cout << “Derivd::f(double d)” << endl;
  18.     }
  19. };
  20. int main()
  21. {
  22.     Derived d;
  23.     d.f(3);
  24.     d.f(2.5);
  25.     Derived *pd = new Derived();
  26.     pd->f(3);
  27.     pd->f(2.5);
  28.     Base b;
  29.     b.f(5);
  30.     b.f(3.5);
  31.     Base *pBase = new Derived();
  32.     pBase->f(5);
  33.     pBase->f(3.5);
  34. }
  35. #include <iostream>
  36. using namespace std;
  37. class Base
  38. {
  39. public:
  40.  virtual void f(int a) {
  41.   cout << “virtual Base::f(int a)” << endl;
  42.  }
  43.  void f(double d) {
  44.   cout << “Base::f(double d)” << endl;
  45.  }
  46. };
  47. class Derived : public Base
  48. {
  49. public:
  50.  void f(double d) {
  51.   cout << “Derivd::f(double d)” << endl;
  52.  }
  53. };
  54. int main()
  55. {
  56.  Derived d;
  57.  d.f(3);
  58.  d.f(2.5);
  59.  Derived *pd = new Derived();
  60.  pd->f(3);
  61.  pd->f(2.5);
  62.  Base b;
  63.  b.f(5);
  64.  b.f(3.5);
  65.  Base *pBase = new Derived();
  66.  pBase->f(5);
  67.  pBase->f(3.5);
  68. }

其中父类中的void f(double d)隐藏了子类的virtual void f(int a),  void f(double d)函数。

所以在主函数中

  1. Derived d;
  2. d.f(3);
  3. d.f(2.5);
  4. Derived *pd = new Derived();
  5. pd->f(3);
  6. pd->f(2.5);
  7. Derived d;
  8. d.f(3);
  9. d.f(2.5);
  10. Derived *pd = new Derived();
  11. pd->f(3);
  12. pd->f(2.5);只要通过Derived对象或者Derived指针执行f()函数,都只执行void Derived::f(double d)该函数。
  13. [html]
  14. Base *pBase = new Derived();
  15. pBase->f(5);
  16. pBase->f(3.5);
  17. Base *pBase = new Derived();
  18. pBase->f(5);
  19. pBase->f(3.5);

在调用pBase->f(5)时,首先要去pBase类中找到对应需要执行的函数,因为Base类中有两个函数virtual void f(int a) 和 void f(double)重载,因为该实参是5,为int类型,所以要调用virtual void f(int a)函数,因为该f(int a)是一个虚函数,所以再去判断pBase所指向的具体对象,具体对象为Derived子类,再去Derived子类的虚函数表中找到void f(int a)函数。因为Derived子类继承了父类Base的虚函数vitural void f(int a),所以输出 virtual Base::f(int a);

在调用pBase->f(3.5)时,首先要去pBase类中找到对应需要执行的函数,因为因为Base类中有两个函数virtual void f(int a) 和 void f(double)重载,因为该实参是3.5,为double类,所以要调用void f(double d)函数,因为该函数是一个普通成员函数,故直接输出。 void Base::f(double d);

wkiom1hfu23rfy9qaaxg5idciom16-jpg

再举一个例子:

  1. #include <iostream>
  2. using namespace std;
  3. class Base
  4. {
  5. public:
  6.     virtual void f(int a) {
  7.         cout << “virtual Base::f(int a)” << endl;
  8.     }
  9.     void f(double d) {
  10.         cout << “Base::f(double d)” << endl;
  11.     }
  12. };
  13. class Derived : public Base
  14. {
  15. public:
  16.     void f(int a) {
  17.         cout << “virtual Derived::f(int a)” << endl;
  18.     }
  19. };
  20. int main()
  21. {
  22.     Derived d;
  23.     d.f(3);
  24.     d.f(2.5);
  25.     Derived *pd = new Derived();
  26.     pd->f(3);
  27.     pd->f(2.5);
  28.     Base b;
  29.     b.f(5);
  30.     b.f(3.5);
  31.     Base *pBase = new Derived();
  32.     pBase->f(5);
  33.     pBase->f(3.5);
  34. }
  35. #include <iostream>
  36. using namespace std;
  37. class Base
  38. {
  39. public:
  40.  virtual void f(int a) {
  41.   cout << “virtual Base::f(int a)” << endl;
  42.  }
  43.  void f(double d) {
  44.   cout << “Base::f(double d)” << endl;
  45.  }
  46. };
  47. class Derived : public Base
  48. {
  49. public:
  50.  void f(int a) {
  51.   cout << “virtual Derived::f(int a)” << endl;
  52.  }
  53. };
  54. int main()
  55. {
  56.  Derived d;
  57.  d.f(3);
  58.  d.f(2.5);
  59.  Derived *pd = new Derived();
  60.  pd->f(3);
  61.  pd->f(2.5);
  62.  Base b;
  63.  b.f(5);
  64.  b.f(3.5);
  65.  Base *pBase = new Derived();
  66.  pBase->f(5);
  67.  pBase->f(3.5);
  68. }

子类Derived中的void f(int a)既覆盖了基类Base的虚函数virtual void f(int a),也隐藏了基类的virtual void f(int a),  void f(double d)函数。

  1. Derived d;
  2. d.f(3);
  3. d.f(2.5);
  4. Derived *pd = new Derived();
  5. pd->f(3);
  6. pd->f(2.5);
  7. Derived d;
  8. d.f(3);
  9. d.f(2.5);
  10. Derived *pd = new Derived();
  11. pd->f(3);
  12. pd->f(2.5);

同理所有用子类对象或者子类指针来调用f()函数时,都只执行virtual void f(int a),输出virtual Derived::f(int a)

  1. view plaincopyprint?Base *pBase = new Derived();
  2. pBase->f(5);
  3. pBase->f(3.5);
  4. Base *pBase = new Derived();
  5. pBase->f(5);
  6. pBase->f(3.5);

pBase->f(5),首先去Base类中寻找相应的函数,同理Base类中的两个函数virtual void f(int a)和void f(double d)是重载函数,因为实参为5,为int类型,所以我们要调用virtual void f(int a)虚函数,因为该函数是虚函数,所以要去判断pBase指向的具体对象,因为pBase指向的是一个子类的对象,所以需要去子类的虚函数表中取找virtual void f(int a)函数,找到之后,执行该函数,故输出virtual Derived::f(int a)。

pBase->f(3.5),首先去Base类中寻找相应的函数,同理Base类中的两个函数virtual void f(int a)和void f(double d)是重载函数,因为实参为3.5,为double类型,所以我们要调用void f(double d),因为该函数为普通成员函数,故执行输出: void Base::f(double d);

wkiol1hfu23wfbvraaxg5jojips11-jpg

未经允许不得转载:JX BLOG » C++ 成员函数的重载,继承,覆盖和隐藏

赞 (0)

评论 0

评论前必须登录!

登陆 注册