名称隐藏指派生类同名成员完全屏蔽基类同名成员,无论参数、访问权限或类型差异;需用using声明显式引入基类成员以支持重载或恢复可见性。

在 C++ 继承中,Name Hiding(名称隐藏)是指派生类中定义的名称(函数、变量、类型等)会**完全屏蔽**基类中同名的成员,即使参数列表不同、重载不匹配,甚至访问权限不同——只要名字相同,基类成员就不可见,除非显式指定作用域。
名称隐藏不是重载,而是“遮住”
很多人误以为派生类里加个同名函数就是重载,其实不是。C++ 的重载只发生在同一作用域内。而基类和派生类是不同作用域,所以派生类中出现同名成员时,编译器不会去基类里找其他重载版本,而是直接忽略整个基类作用域中的同名项。
- 哪怕基类有
void foo(int),派生类写了void foo(double),调用obj.foo(42)也会报错:找不到匹配的foo(int) - 哪怕基类函数是
public,派生类中只是声明了一个同名的private函数,基类版本依然被隐藏 - 变量、typedef、using 声明同样适用名称隐藏规则
如何让基类成员“重新可见”?用 using 声明
如果想在派生类中保留基类的同名成员(尤其是为了支持重载),必须用 using Base::name; 显式把基类名字引入派生类作用域。
-
using Base::func;会把Base中所有名为func的重载版本都带进来 - 之后你可以在派生类中新增重载,它们与基类版本共同参与重载解析
- 注意:
using只影响名称查找,不改变访问权限;若基类成员是private,using也无法让它变成可访问
构造函数、析构函数和 operator= 不自动继承,也不隐藏(但需注意)
C++11 起支持 using Base::Base; 继承构造函数,此时属于“继承”,不是“隐藏”。但默认情况下:
立即学习“C++免费学习笔记(深入)”;
- 派生类不自动获得基类构造函数,也不隐藏它们(因为根本没声明)
- 派生类定义了自己的
operator=,会隐藏基类的赋值运算符;如需基类版本,也要用using Base::operator=; - 析构函数不会被隐藏,但派生类总会合成自己的析构函数,并自动调用基类析构——这是特殊规则,与名称查找无关
容易踩坑的典型场景
名称隐藏常在不经意间导致编译失败或行为异常:
- 基类有个
void print() const,派生类加了个void print()(非 const 版本)→ 基类 const 版本被隐藏,const obj.print()报错 - 模板基类中有个
value成员,派生类写了int value;→ 模板基类里的value(哪怕是静态成员或 typedef)全被隐藏 - 多重继承时,两个基类都有同名函数,派生类未重写也未
using→ 直接调用会歧义;若派生类自己定义了同名函数,则两个基类版本都被隐藏
基本上就这些。名称隐藏不是 bug,是 C++ 作用域设计的明确规则:派生类作用域优先,基类仅作“后备查找路径”,且一旦名字匹配就停止向上搜索。理解它,才能写出可预期的继承接口。











