C++ 重载、隐藏、覆盖

结合这C++ 代码,深入理解重载(Overload)隐藏(Hide)覆盖(Override,也叫重写) 这三个核心概念,用这段代码作为核心案例,由浅入深地拆解它们的区别和本质。

一、先明确三个概念的核心定义

这三个概念都是 C++ 中函数名复用的场景,但适用范围、规则和目的完全不同,先看一张对比表建立整体认知:

概念中文名称适用范围核心特征本质目的
Overload重载同一个作用域内函数名相同,参数列表(个数/类型/顺序)不同,返回值不影响方便同一功能的不同参数调用
Override覆盖/重写子类与父类之间子类重写父类的虚函数,函数签名(名+参数+const)完全一致实现多态(运行时动态绑定)
Hide隐藏/遮蔽子类与父类之间子类函数名覆盖父类同名函数(无论参数/虚函数与否),编译期静态屏蔽作用域优先原则导致的“遮蔽”

覆盖是特殊的隐藏。

二、结合代码逐个拆解

逐个分析这三个概念,并用扩展代码演示效果。

1. 重载(Overload)—— 同一作用域内的“同名不同参”

核心规则:
  • 必须在同一个类/同一个作用域中;
  • 函数名完全相同;
  • 参数列表必须不同(个数、类型、顺序,三者至少一个不同);
  • 返回值、是否是虚函数不影响重载(但仅返回值不同不算重载)。
代码中的重载案例:

Base 类中,两个 show 函数就是典型的重载

classBase{public:Base(int a):ma(a){}// 重载1:无参 showvirtualvoidshow(){cout<<"Base::show()"<<endl;}// 重载2:带int参数的 show —— 与上面构成重载virtualvoidshow(int i){cout<<"Base::show(int)"<<endl;}private:int ma;};
  • 它们在 Base 这个同一作用域内;
  • 函数名都是 show
  • 参数列表不同(一个无参,一个int参数);
  • 都是虚函数(但即使不是虚函数,依然是重载)。
重载的调用示例:
intmain(){ Base b(10); b.show();// 调用 Base::show() —— 匹配无参版本 b.show(5);// 调用 Base::show(int) —— 匹配int参数版本return0;}

编译期编译器会根据实参类型自动匹配对应的重载函数,这是静态绑定(编译期确定调用哪个)。

2. 覆盖/重写(Override)—— 子类对父类虚函数的“精准替换”

核心规则:
  • 必须在子类与父类之间;
  • 父类函数必须是虚函数(virtual)
  • 子类函数的函数签名完全一致(函数名 + 参数列表 + const/volatile 属性完全相同);
  • 子类函数可以加 override 关键字显式声明(C++11 后推荐,编译器会检查是否真的覆盖)。
代码中的覆盖案例:

Derive 类中的 show() 覆盖了 Base 类中的无参 show()

classDerive:publicBase{public:Derive(int a,int b):Base(a),mb(b){}// 覆盖:与 Base::show() 签名完全一致,且父类是虚函数voidshow()override{cout<<"Derive::show()"<<endl;}// 加override更规范private:int mb;};
  • 父类 Base::show() 是虚函数;
  • 子类 Derive::show() 函数名、参数列表(无参)完全一致;
  • 这就是“覆盖”,目的是实现多态
覆盖的多态调用示例:
intmain(){ Base* ptr =newDerive(1,2);// 父类指针指向子类对象 ptr->show();// 调用 Derive::show() —— 运行时动态绑定(多态)delete ptr;return0;}

输出:Derive::show()
这里因为覆盖了虚函数,运行时会根据对象的实际类型(Derive)调用对应的函数,而不是指针类型(Base),这是动态绑定

3. 隐藏/遮蔽(Hide)—— 子类对父类同名函数的“编译期屏蔽”

核心规则:
  • 必须在子类与父类之间;
  • 子类定义了与父类同名的函数(无论参数是否相同、是否是虚函数);
  • 编译器在编译子类作用域时,会屏蔽父类所有同名函数,即使父类是重载/虚函数;
  • 这是编译期静态行为,与多态无关。
代码中的隐藏案例(重点!):

你的代码中,Derive 类定义了 show(),会隐藏父类 Base 中所有名为 show 的函数(包括 show()show(int)):

intmain(){ Derive d(1,2); d.show();// 正常:调用 Derive::show()// d.show(5); // 编译错误!父类的 show(int) 被隐藏了return0;}

为什么会报错?
因为子类 Derive 中有 show() 函数,编译器在解析 d.show(5) 时,会优先在 Derive 作用域找 show,发现只有无参的 show(),没有 show(int),且不会去父类找(被隐藏了),因此编译失败。

隐藏的其他场景(补充理解):

即使子类函数参数与父类不同,依然会隐藏:

classDerive:publicBase{public:Derive(int a,int b):Base(a),mb(b){}// 子类定义 show(double) —— 与父类 show(int) 不同参,但依然隐藏父类所有 showvoidshow(double d){cout<<"Derive::show(double)"<<endl;}private:int mb;};intmain(){ Derive d(1,2);// d.show(5); // 编译错误!父类 show(int) 被隐藏,子类只有 show(double) d.show(5.0);// 正常:调用 Derive::show(double)return0;}
如何解除隐藏?

如果想在子类中调用父类被隐藏的函数,有两种方式:

  1. using 声明,把父类函数引入子类作用域:
classDerive:publicBase{public:using Base::show;// 解除父类所有 show 函数的隐藏Derive(int a,int b):Base(a),mb(b){}voidshow()override{cout<<"Derive::show()"<<endl;}private:int mb;};// 此时调用正常intmain(){ Derive d(1,2); d.show();// 调用 Derive::show() d.show(5);// 调用 Base::show(int) —— 隐藏被解除return0;}
  1. 显式指定父类作用域调用:
intmain(){ Derive d(1,2); d.Base::show(5);// 直接调用父类的 show(int),不受隐藏影响return0;}

三、容易混淆的点对比

1. 覆盖 vs 重载

维度覆盖(Override)重载(Overload)
作用域跨类(父类→子类)同作用域(同一类)
函数签名必须完全一致必须不同(参数列表)
虚函数要求父类必须是虚函数无要求(可虚可非虚)
绑定方式运行时动态绑定编译期静态绑定

2. 覆盖 vs 隐藏

维度覆盖(Override)隐藏(Hide)
前提父类是虚函数 + 签名一致只要子类有同名函数(无论参数/虚函数)
本质多态的实现方式作用域优先导致的屏蔽
绑定方式运行时动态绑定编译期静态屏蔽
父类函数可用性父类虚函数被“替换”但可通过作用域调用父类同名函数被屏蔽,需显式调用

四、完整演示代码

把上述所有场景整合,可以直接运行测试:

#include<iostream>usingnamespace std;classBase{public:Base(int a):ma(a){}// 重载1:无参虚函数virtualvoidshow(){cout<<"Base::show()"<<endl;}// 重载2:带int参数的虚函数(与上面构成重载)virtualvoidshow(int i){cout<<"Base::show(int) "<<i<<endl;}private:int ma;};classDerive:publicBase{public:using Base::show;// 解除父类show的隐藏(注释掉这行看隐藏效果)Derive(int a,int b):Base(a),mb(b){}// 覆盖:重写父类无参showvoidshow()override{cout<<"Derive::show()"<<endl;}// 新增:子类独有的show(double)(会隐藏父类show,除非加using)voidshow(double d){cout<<"Derive::show(double) "<<d<<endl;}private:int mb;};intmain(){// 1. 测试Base的重载 Base b(10); b.show();// Base::show() b.show(5);// Base::show(int) 5// 2. 测试多态(覆盖) Base* ptr =newDerive(1,2); ptr->show();// Derive::show() —— 动态绑定 ptr->show(6);// Base::show(int) 6 —— 子类未覆盖该版本,调用父类delete ptr;// 3. 测试子类的隐藏与解除 Derive d(1,2); d.show();// Derive::show() d.show(7);// Base::show(int) 7(加using后生效,否则编译错误) d.show(3.14);// Derive::show(double) 3.14 d.Base::show();// 显式调用父类show()return0;}

总结

  1. 重载是同一作用域内“同名不同参”,编译期静态匹配,目的是简化调用;
  2. 覆盖是子类重写父类虚函数(签名一致),运行时动态绑定,是多态的核心;
  3. 隐藏是子类同名函数屏蔽父类所有同名函数(编译期行为),需用 using 或作用域显式调用父类函数。

这三个概念的核心区别在于作用域绑定时机:重载是“同作用域+编译期”,覆盖是“跨类+运行期”,隐藏是“跨类+编译期屏蔽”。


补充

#include<iostream>usingnamespace std;classBase// Base base(10);{public:Base(int a):ma(a){}// 虚函数virtualvoidshow(){cout<<"Base::show()"<<endl;}virtualvoidshow(int i){cout<<"Base::show(int)"<<endl;}private:int ma;};classDerive:publicBase{public:Derive(int a,int b):Base(a),mb(b){}voidshow(){cout<<"Derive::show"<<endl;}private:int mb;};

补充说明

  1. 虚函数与重写
    • Base 类中定义了两个虚函数 show()show(int i)
    • Derive 类重写了无参版本 show(),但没有重写带参版本 show(int i)
    • 由于 C++ 的名称隐藏规则Derive 类中定义的 show() 会隐藏掉基类中所有名为 show 的函数(包括 show(int i))。

典型调用行为

intmain(){ Derive d(1,2); d.show();// 正确,调用 Derive::show()// d.show(10); // 编译错误!基类的 show(int) 被隐藏了return0;}

如果想在 Derive 中也能调用 Base::show(int),需要在 Derive 中添加 using Base::show; 来解除名称隐藏。

Read more

C++之《程序员自我修养》读书总结(5)

C++之《程序员自我修养》读书总结(5)

《程序员自我修养》读书总结(五) Author: Once Day Date: 2026年2月12日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 书籍阅读_Once-Day的博客-ZEEKLOG博客 参考文章:《程序员的自我修养》读书笔记 | Zachary’s blog《程序员的自我修养》阅读笔记 - T0fV404 - 博客园读书笔记:《程序员的自我修养》 - 楷哥 - 博客园 文章目录 * 《程序员自我修养》读书总结(五) * 5. Windows PE/COFF 格式 * 5.1 发展历史 * 5.2 mingw-w64 工具链 * 5.

By Ne0inhk
面试官问 C++ 多态?虚函数重写 + 虚表指针 + 动态绑定,核心考点全覆盖

面试官问 C++ 多态?虚函数重写 + 虚表指针 + 动态绑定,核心考点全覆盖

✨ 孤廖:个人主页 🎯 个人专栏:《C++:从代码到机器》 🎯 个人专栏:《Linux系统探幽:从入门到内核》 🎯 个人专栏:《算法磨剑:用C++思考的艺术》 折而不挠,中不为下 文章目录 * 正文: * 1. 多态的概念 * 2. 多态的定义及实现 * 2.1 虚函数 * 2.2 虚函数的重写/覆盖 * 2.3 虚函数重写的⼀些其他问题 * 2.4 override 和 final关键字 * 2.5 重载/重写/隐藏的对⽐ * 3. 纯虚函数和抽象类 * 4. 多态的原理 * 4.1 多态是如何实现的 * 4.2

By Ne0inhk
《C++ 递归、搜索与回溯》第2-3题:合并两个有序链表,反转链表

《C++ 递归、搜索与回溯》第2-3题:合并两个有序链表,反转链表

🔥个人主页:Cx330🌸 ❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》 《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔 《Git深度解析》:版本管理实战全解 🌟心向往之行必能至 🎥Cx330🌸的简介: 目录 前言: 2. 合并两个有序链表 算法原理(递归): 思路: 解法代码(C++): 博主手记(字体还请见谅哈): 3. 反转链表 算法原理(递归): 思路: 解法代码(C++): 博主手记(字体还请见谅哈): 结尾: 前言: 聚焦算法题实战,系统讲解三大核心板块:“精准定位最优解”——优选算法,“简化逻辑表达,系统性探索与剪枝优化”——递归与回溯,“以局部最优换全局高效”——贪心算法,讲解思路与代码实现,帮助大家快速提升代码能力 2.

By Ne0inhk
千面之法: 释放 C++ 多态的灵活威力

千面之法: 释放 C++ 多态的灵活威力

目录 1:多态的概念 1.1:概念 2.多态的定义与实现 2.1:多态的构成条件 2.2:虚函数 2.3:虚函数的重写 2.3.1:虚函数重写的两个例外 2.3.1.1:协变(基类与派生类函数的返回值不同,基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用时) 2.3.1.2:析构函数的重写 2.4:C++11 override和final 2.4.1:final关键字 2.4.2:override关键字 2.5:重载、

By Ne0inhk