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