c++成员函数的重载、覆盖、隐藏区别
#include <iostream>using namespace std;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;}
};int main(void)
{Derived d;Base *pb = &d;pb->f(42); // Base::f(int) 42pb->f(3.14f); // Base::f(float) 3.14pb->g(); // Derived::g(void)return 0;
}
令人迷惑的隐藏规则
本来仅仅区别重载与覆盖并不算困难,但是C++的隐藏规则使问题复杂性陡然增加。
这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual
关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
以下示例中:
(1)函数Derived::f(float) 覆盖了 Base::f(float)。
(2)函数Derived::g(int) 隐藏了 Base::g(float),而不是重载。
(3)函数Derived::h(float) 隐藏了 Base::h(float),而不是覆盖。
#include <iostream>using namespace std;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; }
};
“隐藏”的发生可谓神出鬼没,常常产生令人迷惑的结果。
如以下示例中,pb和 pd 指向同一地址,按理说运行结果应该是相同的,可事实并非这样。
int main(void)
{Derived d;Base *pb = &d;Derived *pd = &d;pb -> f(3.14f); // Derived::f(float) 3.14pd -> f(3.14f); // Derived::f(float) 3.14pb -> g(3.14f); // Base::g(float) 3.14pd- > g(3.14f); // Derived::g(int) 3 (surprise!)pb -> h(3.14f); // Base::h(float) 3.14 (surprise!)pd -> h(3.14f); // Derived::h(float) 3.14return 0;
}
摆脱隐藏
隐藏规则引起了不少麻烦。示例8-2-3 程序中,语句pd->f(10)的本意是想调用函数 Base::f(int),但是 Base::f(int) 不幸被 Derived::f(char *str) 隐藏了。由于数字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
}
c++成员函数的重载、覆盖、隐藏区别相关推荐
- 深入理解成员函数的重载、隐藏、覆盖规则(二)
本文作者:islwj 本文出处:http://blog.csdn.net/islwj 声明: 本文可以不经作者同意, 任意复制, 转载, 但任何对本文的引用都请保留文章开始前三行的作者, 出处以及声明 ...
- C++中类成员函数的重载、覆盖和隐藏的区别,超清楚!
转载:https://www.cnblogs.com/liubo1/p/5925746.html 1.成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: ...
- C++成员函数的重载、覆盖与隐藏
C++成员函数的重载.覆盖与隐藏 成员函数的重载.覆盖(override)与隐藏很容易混淆,C++程序员必须要搞清楚概念,否则错误将防不胜防. 重载与覆盖 成员函数被重载的特征: (1)相同的范围(在 ...
- 成员函数的重载、覆盖与隐藏(详细)【转】
(转自:https://blog.csdn.net/weixin_42205987/article/details/81569744) 成员函数的重载.覆盖与隐藏 成员函数的重载(overload). ...
- c++ 重载 覆盖 隐藏的区别和执行方式
成员函数被重载的特征(1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual 关键字可有可无. 覆盖是指派生类函数覆盖基类函数,特征是 (1)不同的范围(分别位 ...
- 成员函数的重载,覆盖与隐藏
重载 具有相同的作用域(即同一个类定义中) 函数名字相同 参数类型.顺序或数目不同(包括const参数和非const参数) virtual关键字可有可无 覆盖 是指派生类重新实现(或改写)了基类的成员 ...
- C++之常引用对象只能调用常成员函数、重载为成员函数和友元函数的区别
近日写了一道题,遇到了新bug,使博主对C++的逻辑严密性有了更深的体会,特写此博客.本文标题是对两个bug的总结,即本文内容分为两部分. 题目如下: 设计一个CShape抽象类,类中包含纯虚函数 ...
- 问题:1.sizeof;2.重载覆盖隐藏;3.内存管理
1-1.问:"char a[10]; int len = strlen(a);",len等于多少? 解析:strlen计算从数组a的第一个元素开始到'\0'总共有多少个字符(不包含 ...
- C++——运算符的重载---以成员函数方式重载---以友元函数方式重载
一.运算符的重载 1.运算符的重载 允许把标准运算符(如+ - * /等运算符)应用于自定义数据类型的对象,可以提高程序的可读性,运算符的重载本质上还是函数重载.运算符仅仅是语法上的方便,它是另一种函 ...
最新文章
- Linux工具之curl与wget高级使用
- html字体阴影怎么设置6,css怎么设置字体阴影
- 嗨淘V12刷任务点赞系统源码手动派单版本
- Server Host Cannot be null解决方法
- 运维:使用awk命令获取文本的某一行,某一列
- 记一次反制追踪溯本求源
- JavaScript中this指针指向的彻底理解
- DEDECMS v5.7 实现导航条下拉二级菜单
- 移动端学习笔记(黑马教程)-仿京东首页
- 计算机word制作成绩单,如何用word批量制作学生成绩单?
- 【计算机基础恶补】南桥北桥
- 基于微信小程序的物流仓储系统
- C#与C++混合编程及性能分析
- 物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序
- 游戏服务器租用配置选择攻略(大型端游及中小型网页游戏选型)
- 华为云对象存储连接测试
- NSString NSArray NSDictionary NSSet 中的部分方法
- mac lion 系统安装
- VS2017 打包exe,msi文件
- 艾森豪威尔时间管理法则
热门文章
- Object.defineProperty()
- Java--对象与类(三)
- LightHouse/归并排序
- Protocol Buffers简明教程
- css中float用法
- 2022-2028年中国成人艺术培训行业市场前瞻与投资战略规划分析报告
- oracle手工启动,SQLSERVER服务手工启动 批处理文件
- Swift 中 insetBy(dx: CGFloat, dy: CGFloat) - CGRect 用法详解
- FFmpeg学习4:音频格式转换
- Spark源码分析之七:Task运行(一)