重载、覆盖和隐藏的区别

分类: C++ 学习笔记 学习心得与方法 2013-09-26 11:21 50人阅读 评论(0) 收藏 举报

“overload”翻译过来就是:超载,过载,重载,超出标准负荷;“override”翻译过来是:重置,覆盖,使原来的失去效果。

  先来说说重载(Overload)的含义,在日常生活中我们经常要清洗一些东西,比如洗车、洗衣服。尽管我们说话的时候并没有明确地说用洗车的 方式来洗车,或者用洗衣服 的方式来洗一件衣服,但是谁也不会用洗衣服的方式来洗一辆车,否则等洗完时车早就散架了。我们并不要那么明确地指出来就心知肚明,这就有重载的意思了。在 同一可访问区内被声名的几个具有不同参数列的(参数的类型、个数、顺序不同)同名函数,程序会根据不同的参数列来确定具体调用哪个函数,这种机制叫重载, 重载不关心函数的返回值类型。这里,“重载”的“重”的意思不同于“轻重”的“重”,它是“重复”、“重叠”的意思。例如在同一可访问区内有:
  ① double calculate(double);
  ② double calculate(double,double);
  ③ double calculate(double, int);
  ④ double calculate(int, double);
  ⑤ double calculate(int);
  ⑥ float calculate(float);
  ⑦ float calculate(double);
  六个同名函数calculate,①②③④⑤⑥中任两个均构成重载,⑥和⑦也能构成重载,而①和⑦却不能构成重载,因为①和⑦的参数相同。

函数重载:两个函数的形式参数必须不同(比如参数类型、参数个数和参数顺序,这三者中必须至少有一个不同),而函数的返回值类型可以相同也可以不相同,也就是说函数的返回值类型与函数是否发生重载是没有关系的。
  覆盖(Override)是指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一
致,覆盖函数和被覆盖函数只有函数体
(花括号中的部分)不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做覆盖。
  下面我们从成员函数的角度来讲述重载和覆盖的区别。

  成员函数被重载的特征有:
  1) 相同的范围(在同一个类中);
  2) 函数名字相同;
  3) 参数不同;
  4) virtual关键字可有可无。

  覆盖的特征有:
  1) 不同的范围(分别位于派生类与基类);
  2) 函数名字相同;
  3) 参数相同;
  4) 基类函数必须有virtual关键字。

  比如,在下面的程序中:

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. void f(int x){cout<<"A::f(int) "<<x<<endl;}
  7. void f(float x){cout<<"A::f(float) "<< x<<endl;}
  8. virtual void g(void){cout<< "A::g(void)"<<endl;}
  9. };
  10. class B : public A
  11. {
  12. public:
  13. virtual void g(void){cout<<"B::g(void)"<<endl;}
  14. };
  15. int  main(void)
  16. {
  17. B d;
  18. A *p = &d;
  19. p->f(42); // 运行结果:A::f(int) 42
  20. p->f(3.14f); // 运行结果:A::f(float) 3.14
  21. d.g();// 运行结果:B::g(void)
  22. p->g(); // 运行结果:B::g(void)
  23. /*
  24. 运行结果显示:
  25. A::f(int) 42
  26. A::f(float) 3.14
  27. B::g(void)
  28. B::g(void)
  29. 请按任意键继续. . .
  30. */
  31. return 0;
  32. }

  函数A::f(int)与A::f(float)相互重载,而A::g(void)被B::g(void)覆盖。

  隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
  1) 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
  2) 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

  比如,在下面的程序中:

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. virtual void f(float x){cout<<"A::f(float) "<<x<<endl;}//虚函数
  7. void g(float x){cout<<"A::g(float) "<<x<<endl;}
  8. void h(float x){cout<<"A::h(float) "<<x<<endl;}
  9. };
  10. class B : public A
  11. {
  12. public:
  13. virtual void f(float x){cout<<"B::f(float) "<<x<<endl;}//虚函数
  14. void g(int x){cout<<"B::g(int) "<<x<<endl;}
  15. void h(float x){cout<<"B::h(float) "<<x<<endl;}
  16. using A::g;//这句话是用来引用父类中被隐藏的部分的。
  17. };
  18. int main(void)
  19. {
  20. B test1;
  21. A *p = &test1;
  22. test1.g(99);//B::g(int) 99
  23. test1.h(88.8);//B::h(float) 88.8
  24. //下面显示了虚函数的功能
  25. test1.f(66.6);//B::f(float) 66.6
  26. p->f(55.5);//B::f(float) 55.5
  27. A test2;
  28. p = &test2;
  29. p->f(33.3);//A::f(float) 33.3
  30. /*
  31. 输出结果是:
  32. B::g(int) 99
  33. B::h(float) 88.8
  34. B::f(float) 66.6
  35. B::f(float) 55.5
  36. A::f(float) 33.3
  37. 请按任意键继续. . .
  38. */
  39. return 0;
  40. }

通过分析可知:
(1. 函数B::g(int)隐藏了A::g(float),注意,不是重载。
(2. 函数B::h(float)隐藏了A::h(float),注意,不是覆盖。
(3. 函数B::f(float)覆盖了A::f(float),有virtual。

  看完前面的示例,可能大家还没明白隐藏与覆盖到底有什么区别,因为我们前面都是讲的表面现象,怎样的实现方式,属于什么情况。下面我们就要分析覆盖与
隐藏在应用中到底有什么不同之处。在下面的程序中bp和dp指向同一地址,按理说运行结果应该是相同的,可事实并非如此。

  1. <pre class="cpp" name="code">int main(void)
  2. {
  3. B b;
  4. A *p_a = &b;
  5. B *p_b = &b;
  6. //good:behavior依赖于对象的类型
  7. p_a->f(3.14f);
  8. p_b->f(3.14f);
  9. //bad:bahavior依赖于指针类型
  10. p_a->g(3.14f);
  11. p_b->g(3.14f);
  12. //bad:behavior依赖于指针类型
  13. p_a->h(3.14f);
  14. p_b->h(3.14f);
  15. /*
  16. B::f(float) 3.14
  17. B::f(float) 3.14
  18. A::g(float) 3.14
  19. B::g(int) 3
  20. A::h(float) 3.14
  21. B::h(float) 3.14
  22. 请按任意键继续. . .
  23. */
  24. return 0;
  25. }</pre><br>

原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/database/348/12279348.shtml

ZT C++ 重载、覆盖和隐藏的区别的更多相关文章

  1. java的重载、覆盖和隐藏的区别

    重载:方法名相同,但参数不同的多个同名函数 注意:1.参数不同的意思是参数类型.参数个数.参数顺序至少有一个不同 2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg ...

  2. C++中重载、覆盖和隐藏的区别,以及适用场景

    一.重载.覆盖和隐藏的区别 二.适用场景 1.重载: 适用于不同的数据类型都需要使用到的功能函数.以数据相加的函数为例,可以在同一个文件内提供以下的重载函数以支持同样的功能: int add(int, ...

  3. Java_类和对象(完美总结)_转载_覆盖和隐藏的区别,覆盖就不能使用了,而隐藏提供全局方法名或者全局变量名还可以使用

    转载自海子:http://www.cnblogs.com/dolphin0520/p/3803432.html Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封 ...

  4. C++中重载、覆盖与隐藏的区别(转)

    本文摘自林锐博士的<高质量C++/C编程指南>. 成员函数的重载.覆盖(override)与隐藏很容易混淆,C++程序员必须要搞清楚概念,否则错误将防不胜防. 1.重载与覆盖 成员函数被重 ...

  5. C++之重载覆盖和隐藏

    继承体系下同名成员函数的三种关系 重载 在同一作用域内 函数名相同,参数列表不同(分三种情况:参数个数不同,参数类型不同,参数个数和类型都不同) 返回值类型可以相同也可以不同 重写(覆盖) 在不同作用 ...

  6. C++类成员函数的重载、覆盖和隐藏区别?

    C++类成员函数的重载.覆盖和隐藏区别? a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函数覆 ...

  7. 【转】c++重载、覆盖、隐藏——理不清的区别

    原文网址:http://blog.sina.com.cn/s/blog_492d601f0100jqqm.html 再次把林锐博士的<高质量c++编程指南>翻出来看的时候,再一次的觉得这是 ...

  8. C++:类成员函数的重载、覆盖和隐藏区别?

    #include <iostream> class A { public: void func() { std::cout << "Hello" <& ...

  9. C++中重载、重写(覆盖)和隐藏的区别实例分析

    这篇文章主要介绍了C++中重载.重写(覆盖)和隐藏的区别,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下 本文实例讲述了C++中重载.重写(覆盖)和隐藏的区别,对于C++面向对象程序设计 ...

随机推荐

  1. 从fis中得来的数据结构,Object版,

    /* * config * caoke */ 'use strict'; //You can't use merge in util.js function merge(source, target) ...

  2. hdu1395 2^x mod n = 1(欧拉函数)

    2^x mod n = 1 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  3. Python I/O及FIle方法

    一.文件操作 文件的编码格式: ASCII与UNICODE: 计算机有256个ASCII字符(8个0/1的排列组合方式一共有256种, 2**8) UTF-8是UNICODE的一种编码格式,计算机中使 ...

  4. Spark遇到的报错和坑

    1. Java版本不一致,导致启动报错. # 解决方法: 在启动脚本最前边添加系统参数,指定Java版本 export JAVA_HOME=/usr/java/jdk1..0_181-amd64/jr ...

  5. How to download Heavy Duty Diagnostic Caterpillar SIS 2018 software

    Maybe you find there are supplied Caterpillar SIS 2018 software free download in search engine, that ...

  6. linux运维基础之系统挂载与etc文件下介绍

    1) 目录结构说明: windows:磁盘----分区---格式化--系统 linux:磁盘--分区--生成一个文件(磁盘分区) linux 中一切皆文件 ll -h 显示人类能看懂的 mount - ...

  7. HUID 5558 Alice's Classified Message 后缀数组+单调栈+二分

    http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做 ...

  8. Java实现Ip代理池

    设置Ip代理很多时候都会有用到,尤其是在写爬虫相关项目的时候.虽然自己目前没有接触这种需求,但由于最近比较闲,就写着当作练习吧 爬取代理IP 爬取 关于爬取代理IP,国内首先想到的网站当然是 西刺代理 ...

  9. Nginx启动关闭和重启、文档直接下载不阅览

    nginx启动相关 启动:sbin/nginx -c conf/nginx.conf 关闭:sbin/nginx -s stop 重启(重新加载配置文件):sbin/nginx -s reload 检 ...

  10. 深入理解JavaScript系列(30):设计模式之外观模式

    介绍 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用. 正文 外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦 ...