覆盖与重载与隐藏——SAP电面(3)
参考:http://man.chinaunix.net/develop/c&c++/c/c.htm#_Toc520634042
8.2.1 重载与覆盖
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
示例8-2-1中,函数Base::f(int)与Base::f(float)相互重载,而Base::g(void)被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) } |
示例8-2-1成员函数的重载和覆盖
8.2.2 令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,但是C++的隐藏规则使问题复杂性陡然增加。这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
示例程序8-2-2(a)中:
(1)函数Derived::f(float)覆盖了Base::f(float)。
(2)函数Derived::g(int)隐藏了Base::g(float),而不是重载。
(3)函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。
#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; } }; |
示例8-2-2(a)成员函数的重载、覆盖和隐藏
据作者考察,很多C++程序员没有意识到有“隐藏”这回事。由于认识不够深刻,“隐藏”的发生可谓神出鬼没,常常产生令人迷惑的结果。
示例8-2-2(b)中,bp和dp指向同一地址,按理说运行结果应该是相同的,可事实并非这样。
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 } |
示例8-2-2(b) 重载、覆盖和隐藏的比较
8.2.3 摆脱隐藏
隐藏规则引起了不少麻烦。示例8-2-3程序中,语句pd->f(10)的本意是想调用函数Base::f(int),但是Base::f(int)不幸被Derived::f(char *)隐藏了。由于数字10不能被隐式地转化为字符串,所以在编译时出错。
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 } |
示例8-2-3 由于隐藏而导致错误
从示例8-2-3看来,隐藏规则似乎很愚蠢。但是隐藏规则至少有两个存在的理由:
u 写语句pd->f(10)的人可能真的想调用Derived::f(char *)函数,只是他误将参数写错了。有了隐藏规则,编译器就可以明确指出错误,这未必不是好事。否则,编译器会静悄悄地将错就错,程序员将很难发现这个错误,流下祸根。
u 假如类Derived有多个基类(多重继承),有时搞不清楚哪些基类定义了函数f。如果没有隐藏规则,那么pd->f(10)可能会调用一个出乎意料的基类函数f。尽管隐藏规则看起来不怎么有道理,但它的确能消灭这些意外。
示例8-2-3中,如果语句pd->f(10)一定要调用函数Base::f(int),那么将类Derived修改为如下即可。
class Derived : public Base
{
public:
void f(char *str);
void f(int x) { Base::f(x); }
};
转载于:https://www.cnblogs.com/alanhu/p/4570247.html
覆盖与重载与隐藏——SAP电面(3)相关推荐
- C++中的覆盖(重写)、重载、隐藏(重定义)、多态!
例一: 首先声明Base类型的指针指向实际类型为Derived的对象,先调用基类构造函数,再调用派生类构造函数.输出Base, Derived. base->echo(); 指针是base类型, ...
- C++ 函数重载、隐藏与覆盖的区别
代码编译运行环境:VS2017+Debug+Win32 1.函数重载(Function Overload) 1.1 定义 C++ 规定在同一作用域中,同名函数的形式参数(指参数的个数.类型或者顺序)不 ...
- 深入理解成员函数的重载、隐藏、覆盖规则(二)
本文作者:islwj 本文出处:http://blog.csdn.net/islwj 声明: 本文可以不经作者同意, 任意复制, 转载, 但任何对本文的引用都请保留文章开始前三行的作者, 出处以及声明 ...
- Java知多少(29)覆盖和重载
在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类 ...
- “类的使用”编程规范(一)覆写(重写)、重载、隐藏、遮蔽、遮掩
"类的使用"编程规范(一) 1调用静态方法的注意事项 当子类继承父类的静态方法时,如果直接用实例来调用就会将子类中的静态方法隐藏,结果显示为父类的静态方法. package Tas ...
- 遮掩java_关于java中的覆写、重载、隐藏、遮掩、遮蔽
最近在重新学习java,发现了以前未发现的几个概念,从网上搜索了一些资料,现在整理下.对于我来说,以前只是知道java中的覆写 重载和隐藏,这次却发现还有遮掩和遮蔽这两个概念.下面是整理的一篇文章. ...
- SAP 电商云 Spartacus UI 产品搜索结果的设计明细
我们使用如下 url 访问 SAP 电商云 Spartacus UI 产品搜索页面: http://localhost:4000/electronics-spa/en/USD/search/sony ...
- Mobile first 设计思路在 SAP 电商云 Spartacus UI 中的设计体现一例
关于 Mobile First 的概念,请查看我这篇文章:什么是前端开发中的 mobile first 策略. 下图是 SAP 电商云 Spartacus UI 的搜索结果页面: 其布局设计:temp ...
- 如何在 SAP 电商云 Spartacus UI 中创建新的页面
Spartacus 中的页面基于使用相关 API 从 SAP Commerce 后端获取的 CMS 页面.来自 SAP Commerce 端的数据定义了元数据,如 url.标题等,以及页面的结构.结构 ...
最新文章
- 揭露Windows中各种不老实的服务
- 指定的文件夹没有包含设备的兼容软件驱动程序_Windows 10 2020年5月更新兼容性问题汇总...
- 线性O(N)时间复杂度求素数 , 筛法
- android stackview,Android StackView 使用示例
- 数据安全管理:RSA加密算法,签名验签流程详解
- 4000字超干货!《统计学习方法》啃书指南
- 在Mac中用快捷键快速插入日期时间
- 45个python入门案例_给Python小白看的10个使用案例,入门Python就在这里了
- QT安装后编译错误怎么办?
- linux抓肉鸡入侵详细教程,Linux XOR.DDoS入侵排查步骤 | 聂扬帆博客
- 用计算机弹让我做你的眼睛,童珺 - 让我做你的眼睛 (改编版)-酷歌词...
- word参考文献编号、引用、修改
- 使用jquery完成抽奖图片滚动的效果
- 易语言 获取TeamViewerID密码 部分代码
- 阻塞(blockage)设置优化——Hard,Soft,Partial
- omap4430驱动
- 美容仪皮秒机Lumina电源维修CCPF-4000
- R语言学习笔记4_参数估计
- HOW TO:菜单名称有关操作
- 16S rdna 菌种鉴定
热门文章
- 安装虚拟机Ubuntu,搭建lnmp环境碰到的坑(二)
- 【PAT (Advanced Level) Practice】1113 Integer Set Partition (25 分)
- 【深度学习】眼底图像的视杯和视盘分割解析
- Java 按位与 Java代码_(Java)按位与运算符-是否用于减少前一个位间隔?
- mysql学_MySQL学习(一)
- http协议报文体_HTTP协议详解
- debain apt oracle jdk,debian安装oracle jdk
- linux mysql忘记root_linux下mysql-5.6忘记root密码,重置root密码详细过程
- feign session 调用_springboot使用feign调用session传递失效解决方案
- 为什么我的开发方式如此愚蠢?