0

0

C++怎么理解Name Hiding(名称隐藏)_C++作用域与继承中的名称解析

穿越時空

穿越時空

发布时间:2025-11-25 16:26:02

|

758人浏览过

|

来源于php中文网

原创

名称隐藏指派生类同名成员会隐藏基类所有同名函数或变量,即使参数不同;例如Derived中定义func(double)后,Base中的func()和func(int)均被隐藏,导致d.func()和d.func(10)报错;解决方法包括使用using Base::func引入基类重载集,或通过Base::func显式调用;该行为源于C++名称查找从内层作用域开始且一旦命中即停止的规则,适用于函数与变量,需显式处理以恢复基类成员访问。

c++怎么理解name hiding(名称隐藏)_c++作用域与继承中的名称解析

在C++中,Name Hiding(名称隐藏)是一个容易被忽视但非常关键的语言特性,尤其在涉及继承和作用域时表现明显。理解它有助于避免看似正确的代码产生意外行为。

什么是名称隐藏?

当派生类中定义了一个与基类同名的成员(函数、变量等),无论参数是否相同,基类中的所有同名成员都会被隐藏——这就是名称隐藏。

注意:这不同于重载(overloading),因为重载发生在同一作用域内,而继承会引入不同作用域。

示例说明:

考虑以下代码:

立即学习C++免费学习笔记(深入)”;

class Base {
public:
    void func() { cout << "Base::func()" << endl; }
    void func(int x) { cout << "Base::func(int)" << endl; }
};

class Derived : public Base {
public:
    void func(double x) { cout << "Derived::func(double)" << endl; }
};

如果调用:

Derived d;
d.func();        // 错误!Base::func() 被隐藏
d.func(10);      // 错误!Base::func(int) 也被隐藏
d.func(3.14);    // 正确,调用 Derived::func(double)

虽然 Base 中有两个 func 重载版本,但在 Derived 中只要定义了同名函数 func,所有基类中的 func 都会被隐藏,哪怕参数不匹配。

如何解决名称隐藏问题?

如果你希望保留基类中的同名函数可用,有以下几种方式:

  • 使用 using 声明:在派生类中显式引入基类的函数
  • class Derived : public Base {
    public:
        using Base::func;  // 引入 Base 的所有 func 版本
        void func(double x) { cout << "Derived::func(double)" << endl; }
    };
      

    此时,d.func()d.func(10) 都可以正常调用。

    ChartGen
    ChartGen

    AI快速生成专业数据图表

    下载
  • 显式调用基类函数:通过作用域操作符 :: 访问
  • d.Base::func();

    这种方式适合临时调用,但不会恢复重载集。

名称查找的规则:从内到外

C++的名称解析遵循作用域查找顺序:编译器从当前作用域开始查找,一旦找到同名符号就停止查找,不会继续搜索外层或基类作用域。

在继承中,派生类是一个“更内层”的作用域。因此:

  • 编译器先在派生类中查找 func
  • 找到后即停止,即使参数不完全匹配也不会去基类找其他重载版本
  • 结果是:即使基类有更合适的重载,也会因“名称已被找到”而无法参与重载决议

变量也会被隐藏

名称隐藏不仅限于函数。例如:

class Base {
protected:
    int value = 100;
};

class Derived : public Base {
private:
    int value;  // 隐藏了 Base::value
public:
    void print() {
        cout << value << endl;     // 输出未初始化的 value
        cout << Base::value << endl; // 显式访问基类成员
    }
};

这种写法容易引发逻辑错误,尤其是当程序员本意是想扩展而非覆盖成员变量时。

基本上就这些。名称隐藏不是bug,而是C++作用域规则的自然结果。关键是意识到:派生类中的同名声明会切断对基类同名成员的直接访问,必须通过 usingBase::name 显式恢复。理解这一点,能写出更安全、可预测的继承代码。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

537

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 6.7万人学习

C 教程
C 教程

共75课时 | 4万人学习

C++教程
C++教程

共115课时 | 12.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号