Chinaunix首页 | 论坛 | 博客
  • 博客访问: 595019
  • 博文数量: 66
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1810
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-23 13:53
个人简介

linux

文章分类

全部博文(66)

文章存档

2016年(1)

2015年(14)

2014年(32)

2013年(19)

分类: C/C++

2014-11-25 19:59:42

1.成员函数的重载、覆盖与隐藏
    成员函数的重载、覆盖(override)与隐藏很容易混淆,C++程序员必须要搞清楚概念,否则错误将防不胜防。
1.1重载与覆盖
    成员函数被重载的特征:
    (1)相同的范围(在同一个类中)
    (2)函数名字相同
    (3)参数不同
    (4)virtual关键字可有可无
    覆盖是指派生类函数覆盖基类函数,特征是:
    (1)不同的范围(分别位于派生类与基类)
    (2)函数名字相同
    (3)参数形同
    (4)基类函数必须有virtual关键字
    示例中,函数Base::f(int)与Base::f(float)相互重载,而Base::g(void)被Derived::g(void)覆盖。
     
  1. #include <iostream>
  2. using namespace std;

  3. class Base
  4. {
  5. public:
  6.         //f(int) and f(float) is overload function
  7.         void f(int x)
  8.         {
  9.                 cout << "Base::f(int)" << endl;
  10.         }

  11.         void f(float x)
  12.         {
  13.                 cout << "Base::f(float)" << endl;
  14.         }
  15.         //virtual override
  16.         virtual void g(void)
  17.         {
  18.                 cout << "Base::g(void)" << endl;
  19.         }

  20. };
  21. class Derived : public Base
  22. {
  23. public:
  24.         virtual void g(void)
  25.         {
  26.                 cout << "Derived::g(void)" << endl;
  27.         }
  28. };

  29. int main()
  30. {
  31.         Derived d;
  32.         Base *pb = &d;

  33.         pb->f(42); //Base::f(int)
  34.         pb->f(3.14f); //Base::f(float)
  35.         pb->g(); //Derived::g();

  36.         return 0;
  37. }
1.2令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,但是C++的隐藏规则使问题复杂性陡然增加。这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
    (1)如果派生类的函数与基类的函数同名, 但参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意b别与重载混淆)
    (2)如果派生类的函数与基类的函数同名, 并且参数也相同, 但是基类的函数没有virtual关键字。此时,基类的函数将被隐藏(注意别与覆盖混淆)
     示例程序(a)中:
    (1)函数Derived::f(float)覆盖了Base::f(float)。
    (2)函数Derived::g(int)隐藏了Base::g(float),而不是重载。
    (3)函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。

  1. #include <iostream>
  2. using namespace std;

  3. class Base
  4. {
  5. public:
  6.         virtual void f(float x)
  7.         {
  8.                 cout << "Base::f(float) " << x << endl;
  9.         }

  10.         void g(float x)
  11.         {
  12.                 cout << "Base::g(float) " << x << endl;
  13.         }

  14.         void h(float x)
  15.         {
  16.                 cout << "Base::h(float) " << x << endl;
  17.         }
  18. };
  19. class Derived : public Base
  20. {
  21. public:
  22.         //override
  23.         virtual void f(float x)
  24.         {
  25.                 cout << "Derived::f(flaot) " << x << endl;
  26.         }

  27.         //hidden
  28.         void g(int x)
  29.         {
  30.                 cout << "Derived::g(int) " << x << endl;
  31.         }

  32.         //hidden
  33.         void h(float x)
  34.         {
  35.                 cout << "Derived::h(float) " << x << endl;
  36.         }
  37. };
  38. int main()
  39. {
  40.         Derived d;
  41.         Base *pb = &d;
  42.         Derived *pd = &d;

  43.         pb->f(3.14f); //Derived::f(float)
  44.         pd->f(3.14f); //Derived::f(float)


  45.         pb->g(3.14f); //Base::g(float)
  46.         pd->g(3.14f); //Derived::g(int)

  47.         pb->h(3.14f); //Base::h(float)
  48.         pd->h(3.14f); //Derived::h(float)
  49.         return 0;
  50. }
但是隐藏规则至少有两个存在的理由:
      (1)写语句pd->f(10)的人可能真的想调用Derived::f(char *)函数,只是他误将参数写错了。有了隐藏规则,编译器就可以明确指出错误,这未必不是好事。否则,编译器会静悄悄地将错就错,程序员将很难发现这个错误,流下祸根。
      (2)假如类Derived有多个基类(多重继承),有时搞不清楚哪些基类定义了函数f。如果没有隐藏规则,那么pd->f(10)可能会调用一个出乎意料的基类函数f。尽管隐藏规则看起来不怎么有道理,但它的确能消灭这些意外。





阅读(1625) | 评论(0) | 转发(0) |
0

上一篇:内存管理

下一篇:find

给主人留下些什么吧!~~