一文带你深入了解隐藏的相关知识 📅 发布时间:2026/7/8 17:37:56 👁️ 浏览次数: 一文带你深入了解隐藏的相关知识文章目录一文带你深入了解隐藏的相关知识一、什么是隐藏最简单的例子二、隐藏的三种情况1. 成员变量的隐藏2. 成员函数的隐藏3. 重载函数的隐藏三、解决隐藏的方法方法1使用using声明方法2显式调用基类版本四、隐藏 vs 重写覆盖的区别详细解释代码运行结果五、隐藏的实际应用场景场景1加强访问控制场景2修改函数行为但保留接口场景3静态多态CRTP模式中的隐藏六、常见陷阱和注意事项陷阱1意外隐藏陷阱2隐藏与重载的混淆最佳实践建议总结总结好的我来详细讲解C继承中的**隐藏Hiding**机制。这是一个非常重要但也容易混淆的概念。一、什么是隐藏隐藏是指在派生类中定义了与基类同名的成员函数或变量时基类的同名成员在派生类中变得不可见被隐藏了。最简单的例子#includeiostreamusingnamespacestd;classBase{public:voidfunc(){coutBase::func()endl;}};classDerived:publicBase{public:voidfunc(){// 隐藏了基类的funccoutDerived::func()endl;}};intmain(){Derived d;d.func();// 输出Derived::func()基类的被隐藏// 如果想调用基类的必须指定作用域d.Base::func();// 输出Base::func()return0;}二、隐藏的三种情况1. 成员变量的隐藏classBase{public:intvalue100;intsameName10;};classDerived:publicBase{public:intvalue200;// 隐藏了基类的valueintdifferent20;voidprint(){coutDerived value: valueendl;// 200派生类的coutBase value: Base::valueendl;// 100需要指定coutsameName: sameNameendl;// 10基类的没被隐藏}};intmain(){Derived d;d.print();coutd.valueendl;// 200派生类的coutd.Base::valueendl;// 100基类的return0;}2. 成员函数的隐藏这是最容易混淆的地方特别注意隐藏不看参数只看名字classBase{public:voidfunc(){coutBase::func()endl;}voidfunc(intx){coutBase::func(int) xxendl;}voidfunc(doublex){coutBase::func(double) xxendl;}};classDerived:publicBase{public:voidfunc(){// 隐藏了基类中所有名为func的函数coutDerived::func()endl;}};intmain(){Derived d;d.func();// ✅ 调用Derived::func()// d.func(10); // ❌ 错误基类的func(int)被隐藏了// d.func(3.14); // ❌ 错误基类的func(double)也被隐藏了// 必须指定基类作用域才能调用d.Base::func(10);// ✅ 这样才可以d.Base::func(3.14);// ✅ 这样才可以return0;}3. 重载函数的隐藏重要规则派生类中定义同名函数会隐藏基类中所有同名函数不管参数列表classBase{public:voidshow(){coutBase::show()endl;}voidshow(int){coutBase::show(int)endl;}voidshow(double){coutBase::show(double)endl;}};classDerived:publicBase{public:voidshow(){// 隐藏了基类所有的showcoutDerived::show()endl;}};intmain(){Derived d;d.show();// ✅ 调用Derived的// d.show(10); // ❌ 被隐藏了// d.show(3.14); // ❌ 被隐藏了// 解决方案1使用using声明return0;}三、解决隐藏的方法方法1使用using声明classBase{public:voidfunc(){coutBase::func()endl;}voidfunc(int){coutBase::func(int)endl;}};classDerived:publicBase{public:usingBase::func;// 把基类所有func函数引入派生类作用域voidfunc(){// 现在重载而不是隐藏coutDerived::func()endl;}};intmain(){Derived d;d.func();// Derived::func()d.func(10);// Base::func(int)因为using声明return0;}方法2显式调用基类版本classDerived:publicBase{public:voidfunc(){coutDerived::func()endl;}voidcallBaseFunc(){Base::func();// 显式调用基类版本}voidcallBaseFunc(intx){Base::func(x);// 显式调用基类版本}};四、隐藏 vs 重写覆盖的区别这是初学者最容易混淆的一定要分清楚特性隐藏重写覆盖关键字无virtual函数名相同相同参数可不同必须相同返回值可不同必须相同协变除外绑定方式静态绑定动态绑定多态性无有classBase{public:voidhide(){coutBase::hideendl;}// 会被隐藏virtualvoidoverride(){coutBase::overrideendl;}// 会被重写};classDerived:publicBase{public:voidhide(){coutDerived::hideendl;}// 隐藏voidoverride()override{coutDerived::overrideendl;}// 重写};intmain(){Base*ptrnewDerived();ptr-hide();// 静态绑定Base::hide隐藏不看指针实际类型ptr-override();// 动态绑定Derived::overridedeleteptr;return0;}根据你提供的代码ptr-hide();调用的是基类的hide()函数。虽然ptr指向的是一个Derived对象但由于hide()不是虚函数编译器根据指针的静态类型即Base*来决定调用哪个函数这就是静态绑定。详细解释指针类型ptr被声明为Base*类型所以它的静态类型是Base*。函数类型hide()在基类中没有被声明为virtual因此它是一个非虚函数。绑定机制对于非虚函数编译器在编译时就根据指针的静态类型Base*确定了要调用的函数地址所以它会调用Base::hide()。结果因此输出是Base::hide。而override()是虚函数所以调用它时会根据指针指向的对象的实际类型Derived进行动态绑定输出Derived::override。代码运行结果Base::hide // 来自静态绑定 Derived::override // 来自动态绑定总结隐藏hide同名非虚函数由指针/引用的静态类型决定调用哪个版本。重写override同名虚函数由对象的实际类型决定调用哪个版本。五、隐藏的实际应用场景场景1加强访问控制classBase{public:voidpublicAPI(){coutBase public APIendl;}};classDerived:privateBase{public:voidpublicAPI(){// 隐藏基类的publicAPIcoutDeriveds own APIendl;Base::publicAPI();// 可以在内部使用基类的}};intmain(){Derived d;d.publicAPI();// 调用Derived的版本// d.Base::publicAPI(); // ❌ 不能直接调用基类的private继承return0;}场景2修改函数行为但保留接口classLogger{public:voidlog(conststringmsg){cout[LOG] msgendl;}};classTimedLogger:publicLogger{public:voidlog(conststringmsg){// 隐藏基类的logstring timedMsg[getCurrentTime()] msg;Logger::log(timedMsg);// 调用基类版本完成实际工作}private:stringgetCurrentTime(){return12:00:00;// 简化示例}};场景3静态多态CRTP模式中的隐藏templatetypenameDerivedclassBase{public:voidinterface(){static_castDerived*(this)-implementation();// 调用派生类版本}voidimplementation(){// 可能被隐藏coutBase implementationendl;}};classDerived:publicBaseDerived{public:voidimplementation(){// 隐藏基类的implementationcoutDerived implementationendl;}};六、常见陷阱和注意事项陷阱1意外隐藏classBase{public:virtualvoidprocess(intx){coutBase::process(int)endl;}};classDerived:publicBase{public:// 本意是想重写但参数不同变成了隐藏virtualvoidprocess(doublex){// ❌ 隐藏了基类的process(int)coutDerived::process(double)endl;}};intmain(){Derived d;d.process(10);// 调用Derived::process(double)int转double// d.process(10, 20); // 如果基类有其他重载也都被隐藏return0;}陷阱2隐藏与重载的混淆classBase{public:voidf(int){coutBase::f(int)endl;}};classDerived:publicBase{public:voidf(double){coutDerived::f(double)endl;}// 隐藏不是重载};intmain(){Derived d;d.f(10);// 调用Derived::f(double)10被转为double// 想要调用Base::f(int)只能用Base::f(10)return0;}最佳实践建议使用override关键字C11明确表示重写意图classDerived:publicBase{voidfunc()override;// 明确表示要重写};使用using声明引入基类同名函数避免意外隐藏classDerived:publicBase{usingBase::func;// 引入基类所有funcvoidfunc();// 现在是重载集的一部分};避免在派生类中使用与基类相同的名字除非你有明确意图理解并善用作用域解析Base::member来访问被隐藏的成员总结要点说明隐藏的本质派生类的名字屏蔽了基类的同名成员判断依据只看名字不看参数列表影响范围隐藏一个函数会隐藏所有同名函数与重写的区别隐藏是静态绑定重写是动态绑定解决方案using声明或显式作用域常见用途加强封装、修改行为、CRTP模式理解隐藏机制对于正确使用C继承至关重要特别是在设计类层次结构和处理多态时。总结这篇文章是作者搜集大量面经和资料这里出来的。感谢你的支持作者wkm是一名中国矿业大学(北京) 大一的新生希望得到你的关注如果可以的话记得一键三联
2024微信开发者工具从零配置到项目创建全指南 1. 为什么你需要微信开发者工具? 如果你对微信小程序开发感兴趣,或者你的公司业务需要一个小程序,那么微信开发者工具就是你绕不开的“第一站”。简单来说,它就像是你开发微信小程序的“专属工作室”。在这个工作室里,… 2026/7/8 17:33:04
绿色IDC机房设计规范:节能与高效的数据中心建设指南 1. 为什么你的数据中心需要“绿色”转型? 大家好,我是老张,在数据中心这个行当里摸爬滚打了十几年,经手过从几十个机柜到上万平米超大规模数据中心的项目。这些年,我亲眼看着电费账单从成本构成里的小角色,… 2026/7/7 0:21:34
易语言64位端游内存封包逆向实战指南——从基础到精通(传奇4案例解析) 1. 易语言64位逆向:从“小白”到“入门”的认知重塑 很多刚接触游戏逆向的朋友,尤其是从易语言入门的,心里总有个疙瘩:易语言这“中文编程”,搞搞32位的小程序还行,面对现在主流的64位大型端游,… 2026/7/2 22:31:51
Unity点击管理系统:从零构建可扩展的交互架构 1. 项目概述:为什么我们需要一个点击管理系统?在Unity里做UI交互,新手和老手之间往往隔着一道“点击管理”的鸿沟。刚开始做项目时,我们习惯在按钮的OnClick()事件上直接拖拽脚本方法,或者在代码里写一堆GetComponent&… 2026/7/8 17:36:42
UE5动画性能优化:将事件图表逻辑迁移至线程安全函数库 1. 项目概述:为什么我们要从事件图表迁移出去?如果你在UE5里做过稍微复杂一点的动画逻辑,比如根据角色状态实时混合多个蒙太奇,或者根据物理碰撞动态调整骨骼位置,那你大概率在事件图表(Event Graph&#x… 2026/7/8 17:36:42
UE5角色控制进阶:Pawn与Character的灵活选择与深度定制 1. 项目概述:为什么从Pawn到Character是UE5实战的必经之路 如果你在虚幻引擎5里鼓捣过一阵子,尤其是想做个能跑能跳、能打能挨的角色,那你肯定绕不开Pawn和Character这两个类。很多新手教程会告诉你,Character是Pawn的子类&#x… 2026/7/8 17:36:42
UE5.5中利用TMeshAABBTree3实现高性能三角网格碰撞检测 1. 项目概述:为什么我们需要TMeshAABBTree3? 在UE5.5里做游戏,尤其是涉及到大量动态物体、复杂地形或者需要高精度物理交互的场景,碰撞检测的性能瓶颈几乎是每个开发者都会遇到的“坎”。你可能会发现,当场景里有几百个… 2026/7/8 17:34:40
基于TB6593FNG与PIC18F46K20的直流电机控制系统设计 1. 项目背景与核心器件选型在工业自动化和机器人控制领域,直流电机因其优异的调速性能和简单的控制结构而广受欢迎。本次项目采用东芝TB6593FNG驱动芯片与Microchip PIC18F46K20微控制器组合,构建了一套高性价比的直流电机控制系统。这个组合特别适合中小… 2026/7/8 17:32:38
淘宝APP逆向实战:解密x-sign等四神加密算法与自动化请求构建 1. 项目概述:从全栈到逆向,一次对淘宝核心加密的深度探索几年前,我还是个埋头写业务逻辑的全栈开发,直到有一天,一个数据采集的需求让我碰上了淘宝APP这堵加密高墙。那些看似普通的请求里,带着一串串神秘的… 2026/7/8 17:30:37
BetterNCM安装器:高效管理网易云插件的最佳选择 BetterNCM安装器:高效管理网易云插件的最佳选择 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 还在为网易云音乐插件的繁琐安装流程而烦恼吗?BetterNCM安装器是… 2026/7/8 0:02:48
运动控制系统安全设置对比:ECI3808的3种限位保护与急停逻辑实现 运动控制系统安全机制深度解析:限位保护与急停逻辑的设计哲学在精密制造与自动化领域,运动控制系统的安全设计绝非简单的功能堆砌,而是一套融合了机械工程、电气原理和软件算法的防御体系。当一台数控机床以每分钟数万转的速度运转࿰… 2026/7/8 0:06:48
AI大模型应用开发:小白也能抓住的红利风口,收藏这篇入门指南! 文章指出,虽然微软等科技巨头在裁员,但英伟达等公司却在积极扩招AI相关人才,尤其是具身智能、仿真等领域。AI行业正在经历结构性调整,传统岗位被淘汰,而大模型应用开发等新岗位需求旺盛。对于想转行或学习AI的普通人来… 2026/7/8 0:10:49
6个月转型AI工程师:实战路径与核心技能 1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公… 2026/7/7 11:26:57
TPAFE0808与PIC18F87K22的多通道信号采集方案 1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与系统监测是基础且关键的技术需求。传统方案往往面临通道数量不足、信号调理复杂、系统集成度低等问题。TPAFE0808作为一款8通道模拟前端芯片,与PIC18F87K22微控制器的组合… 2026/7/7 11:26:57
STC3115与PIC18LF26K80构建高精度电池管理系统 1. STC3115与PIC18LF26K80在电池管理系统中的核心价值在现代电子设备中,电池管理系统(BMS)的重要性不亚于设备的核心处理器。STC3115作为一款高精度电池电量监测IC,与PIC18LF26K80微控制器的组合,构成了一个既能精确监控又能智能管理的完整解… 2026/7/8 14:25:08