news 2026/9/3 2:13:49

《你真的了解C++吗》No.025:隐藏(Hiding)而非覆盖(Overriding)的陷阱

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《你真的了解C++吗》No.025:隐藏(Hiding)而非覆盖(Overriding)的陷阱

《你真的了解C++吗》No.025:隐藏(Hiding)而非覆盖(Overriding)的陷阱

在解决了菱形继承的物理布局后,我们要面对一个非常隐蔽的逻辑陷阱。很多开发者在写派生类时,本想增强基类的功能,结果却不小心“抹杀”了基类的所有同名函数。

导言:消失的函数

在 C++ 中,我们习惯了重载(Overloading)——在同一个作用域里,函数名相同但参数不同。但在继承体系中,规则发生了剧变。

核心准则:派生类的作用域嵌套在基类的作用域之内。一旦派生类定义了与基类同名的函数,基类的所有同名函数在派生类中都会被立即“隐藏”。


一、 案例拆解:你以为的重载,其实是抹杀

看看这段极具迷惑性的代码:

classBase{public:voidfunc(){std::cout<<"Base::func()\n";}voidfunc(intx){std::cout<<"Base::func(int)\n";}};classDerived:publicBase{public:// 我只想增加一个带 double 参数的版本voidfunc(doubled){std::cout<<"Derived::func(double)\n";}};

当你调用时:

Derived d;d.func(3.14);// 成功,调用 Derived::func(double)d.func(10);// 警告!调用的是 Derived::func(double),10 被隐式转成了 doubled.func();// 编译报错!编译器说 Derived 类里找不到无参的 func()

为什么报错?
编译器在Derived的作用域里找到了func(double),于是它就此打住,不再去Base的作用域里寻找其他func的重载版本。这就是所谓的名字隐藏(Name Hiding)


二、 隐藏(Hiding)vs 覆盖(Overriding)

这是两个极易混淆的概念,它们的物理本质完全不同:

特性覆盖 (Overriding)隐藏 (Hiding)
前提基类函数必须是virtual只要函数名相同就会发生
签名函数签名(参数、返回值)必须完全一致函数名相同即可,参数可以不同
多态运行时的动态绑定编译时的作用域屏蔽
结果通过基类指针能调用到子类实现基类函数在子类中“不可见”

三、 如何找回被隐藏的函数?

如果你确实想在派生类中保留基类的那些重载版本,而不必手动一个个去重写一遍,C++ 提供了一个优雅的武器:using声明。

classDerived:publicBase{public:usingBase::func;// 声明:请把 Base 里的所有名为 func 的函数搬到我的作用域里来voidfunc(doubled){...}};// 现在 Derived 同时拥有了 func(), func(int), func(double)

四、 为什么 C++ 要这样设计?

这看起来像是个设计缺陷,但实际上是为了防止**“远距离干扰”**。
如果基类位于一个遥远的库中,某天库更新增加了一个新的重载版本,而你刚好在派生类里有一个类似名称的函数。如果没有隐藏规则,基类的新函数可能会在不经意间改变你代码的重载解析结果,导致难以排查的 Bug。

隐藏规则强制你:如果你要改,你就得明确知道你在改什么。


总结:作用域的权力

  • 名字查找(Lookup)优先于类型检查。只要名字对上了,编译器就不再往上找了。
  • 在继承体系中,如果你需要重载基类的函数,请务必配合使用using声明。
  • 记住:只有virtual配合相同的签名才是覆盖,其他的统统是隐藏

下一篇预告:聊完了编译器的静态查找,我们要看看运行时最昂贵的操作之一。当你不得不问一个基类指针“你到底是不是某个子类”时,幕后发生了什么?

➡️《你真的了解C++吗》No.026:运行时类型识别(RTTI)的开销——dynamic_cast 的代价。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 19:59:08

Java面试必看:与的区别你真的懂吗?

文章目录Java面试必看&#xff1a;&与&&的区别你真的懂吗&#xff1f;一、基本概念&#xff1a;&与&&的“前世今生”1. &运算符2. &&运算符二、深入解析&#xff1a;&与&&的核心区别1. 短路特性对比使用“&”的情况&#…

作者头像 李华
网站建设 2026/9/2 19:58:38

基于单片机的密闭容器压力检测系统设计(有完整资料)

资料查找方式&#xff1a;特纳斯电子&#xff08;电子校园网&#xff09;&#xff1a;搜索下面编号即可编号&#xff1a;T5032407C设计简介&#xff1a;本设计是基于单片机的密闭容器压力检测系统设计&#xff0c;主要实现以下功能&#xff1a;通过气压传感器检测气压通过气压是…

作者头像 李华
网站建设 2026/9/2 20:37:31

新中地学员转行学GIS开发原因盘点(2)

这一期&#xff0c;我们继续分享另外一个比较普遍的原因&#xff1a;因为不想做外业而选择转行。煤矿探测转GIS开发该同学是某双非一本测绘工程专业&#xff0c;毕业后入职某能源型国企&#xff0c;每月定额下井14次&#xff0c;并负责一些地面技术工作&#xff0c;在煤矿工作一…

作者头像 李华
网站建设 2026/9/2 1:31:34

渗透测试工具包整理:转行网络安全必备的 10 个工具及使用场景

渗透测试工具包整理&#xff1a;转行网络安全必备的 10 个工具及使用场景 引言 刚转行时&#xff0c;我曾陷入 “工具囤积症”—— 下载了几十款安全工具&#xff0c;却不知道什么时候用、怎么用。后来才明白&#xff1a;渗透测试不需要 “全工具”&#xff0c;掌握 10 个核心…

作者头像 李华