同名隐藏基础

同名隐藏

一、什么是同名隐藏?

在继承关系中,如果派生类定义了与基类同名的成员 (数据成员或成员函数),派生类的成员会隐藏基类中同名的成员。这种现象称为同名隐藏

cpp 复制代码
class Object {
public:
    int value;
    int num;      // 基类成员
};

class Base : public Object {
public:
    int num;      // 派生类成员(与基类同名!)
    int sum;
    
    void fun() {
        num = 10;        // 默认访问派生类自己的 num
        // 基类的 num 被隐藏了
    }
};

二、同名隐藏的核心规则

2.1 就近原则

当派生类中定义了与基类同名的成员时,编译器遵循就近原则:优先使用派生类自己的成员。

cpp 复制代码
class Object {
public:
    int num = 100;      // 基类的 num
};

class Base : public Object {
public:
    int num = 200;      // 派生类的 num(同名隐藏)
    
    void fun() {
        cout << num << endl;        // 输出 200(派生类的 num)
        // 基类的 num 被隐藏了
    }
};

2.2 如何访问被隐藏的基类成员?

使用作用域解析运算符 :: 可以强制访问被隐藏的基类成员。

cpp 复制代码
class Object {
public:
    int num;
};

class Base : public Object {
public:
    int num;
    
    void fun() {
        num = 10;              // 访问派生类的 num
        Object::num = 100;     // 访问基类的 num(使用作用域解析)
    }
};

int main() {
    Base base;
    base.num = 20;             // 访问派生类的 num
    base.Object::num = 200;    // 访问基类的 num
    
    return 0;
}

三、数据成员的同名隐藏

3.1 基本示例

cpp 复制代码
#include <iostream>
using namespace std;

class Object {
public:
    int value;
    int num;
    
    Object() : value(0), num(0) {}
};

class Base : public Object {
public:
    int num;      // 同名隐藏:隐藏了 Object::num
    int sum;
    
    Base() : num(100), sum(0) {}  // 派生类的 num 初始化为 100
    
    void fun() {
        sum = 1;
        value = 1;           // value 在 Object 中,没有被隐藏
        num = 10;            // 访问派生类的 num(就近原则)
        
        // 访问被隐藏的基类成员
        Object::num = 100;   // 访问 Object 中的 num
    }
};

int main() {
    Base base;
    
    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    // 内存布局:Object::value(4) + Object::num(4) + Base::num(4) + sum(4) = 16 字节
    
    base.fun();
    
    // 访问派生类的 num
    base.num = 122;          // 修改 Base::num
    cout << "base.num = " << base.num << endl;  // 122
    
    // 访问基类的 num(需要作用域解析)
    base.Object::num = 100; 	 // 修改 Object::num
    cout << "base.Object::num = " << base.Object::num << endl;  // 100
    
    return 0;
}
注意:

基类和派生类各有一份独立的 num,互不影响!

3.3 访问权限对同名隐藏的影响

cpp 复制代码
class Object {
public:
    int pub_num;
protected:
    int pro_num;
private:
    int pri_num;
};

class Base : public Object {
private:
    int pub_num;      // 可以隐藏基类的 public 成员
    int pro_num;      // 可以隐藏基类的 protected 成员
    // int pri_num;   // 不能隐藏基类的 private 成员(不可见)
};

// 结论:只能隐藏基类中可见的成员(public 和 protected)

四、成员函数的同名隐藏

4.1 函数同名隐藏

cpp 复制代码
class Object {
public:
    void func() {
        cout << "Object::func()" << endl;
    }
    
    void func(int x) {
        cout << "Object::func(int): " << x << endl;
    }
};

class Base : public Object {
public:
    // 派生类定义了同名函数(参数不同)
    void func(int x) {      // 隐藏了 Object 中的所有 func 函数!
        cout << "Base::func(int): " << x << endl;
    }
};

int main() {
    Base base;
    
    base.func(12);           // 调用 Base::func(int)
    // base.func();          // 错误!Object::func() 被隐藏了
    // base.func(3.14);      // 错误!Object::func(int) 也被隐藏了
    
    // 使用作用域解析访问被隐藏的基类函数
    base.Object::func();     // 调用 Object::func()
    base.Object::func(20);   // 调用 Object::func(int)
    
    return 0;
}

4.2 重要概念:函数重载 与 同名隐藏

概念 发生条件 作用域 示例
函数重载 同一作用域内,函数名相同,参数不同 同一个类 Base 类中定义多个 func
同名隐藏 不同作用域(基类和派生类),函数名相同 不同类 派生类定义 func,隐藏基类的所有 func
cpp 复制代码
class Object {
public:
    void func() { }      // 函数1
    void func(int) { }   // 函数2(重载)
};

class Base : public Object {
public:
    void func(double) { } // 函数3(不是重载!是隐藏)
    // 此时,函数1和函数2都被隐藏了
};

五、完整代码示例

cpp 复制代码
#include <iostream>
using namespace std;

// ========== 数据成员同名隐藏 ==========
class Object {
public:
    int value;
    int num;
    
    Object() : value(0), num(0) {
        cout << "Object 构造: value=" << value << ", num=" << num << endl;
    }
};

class Base : public Object {
public:
    int num;      // 同名隐藏
    int sum;
    
    Base() : num(100), sum(0) {
        cout << "Base 构造: num(派生)=" << num << ", sum=" << sum << endl;
    }
    
    void fun() {
        cout << "\n=== Base::fun() ===" << endl;
        sum = 1;
        value = 1;              // 访问 Object::value
        num = 10;               // 默认访问 Base::num
        cout << "Base::num = " << num << endl;
        
        // 访问被隐藏的基类成员
        Object::num = 100;      // 访问 Object::num
        cout << "Object::num = " << Object::num << endl;
    }
};

// ========== 成员函数同名隐藏 ==========
class Animal {
public:
    void speak() {
        cout << "Animal::speak()" << endl;
    }
    
    void speak(int times) {
        cout << "Animal::speak(int): " << times << " 次" << endl;
    }
    
    virtual void move() {
        cout << "Animal::move()" << endl;
    }
};

class Dog : public Animal {
public:
    // 同名隐藏:隐藏了 Animal 中所有名为 speak 的函数
    void speak() {
        cout << "Dog::speak(): 汪汪" << endl;
    }
    
    // 虚函数可以被覆盖(override),不是隐藏
    void move() override {
        cout << "Dog::move(): 跑" << endl;
    }
};

int main() {
    cout << "========== 数据成员同名隐藏 ==========" << endl;
    Base base;
    base.fun();
    
    cout << "\n外部访问:" << endl;
    base.num = 200;                    // 修改 Base::num
    cout << "base.num = " << base.num << endl;
    
    base.Object::num = 300;            // 修改 Object::num
    cout << "base.Object::num = " << base.Object::num << endl;
    
    cout << "\n========== 成员函数同名隐藏 ==========" << endl;
    Dog dog;
    
    dog.speak();           // 调用 Dog::speak()
    // dog.speak(3);       // 错误!Animal::speak(int) 被隐藏了
    
    dog.Animal::speak();   // 调用 Animal::speak()
    dog.Animal::speak(5);  // 调用 Animal::speak(int)
    
    dog.move();            // 调用 Dog::move()(虚函数覆盖,不是隐藏)
    
    return 0;
}

六、同名隐藏 与 虚函数覆盖

特性 同名隐藏 虚函数覆盖
关键字 无特殊关键字 virtual / override
函数名相同
参数相同 不一定 必须完全相同
作用 隐藏基类所有同名函数 实现多态
基类函数可见性 被隐藏(需要 :: 访问) 可被覆盖,仍可通过基类指针访问
多态行为 不支持 支持
cpp 复制代码
class Base {
public:
    void hide() { cout << "Base::hide" << endl; }
    virtual void cover() { cout << "Base::cover" << endl; }
};

class Derived : public Base {
public:
    void hide() { cout << "Derived::hide" << endl; }      // 同名隐藏
    void cover() override { cout << "Derived::cover" << endl; } // 覆盖
};

int main() {
    Base* p = new Derived();
    
    p->hide();    // 调用 Base::hide(隐藏不支持多态)
    p->cover();   // 调用 Derived::cover(覆盖支持多态)
    
    return 0;
}

七、总结

7.1 同名隐藏规则总结

成员类型 隐藏规则 如何访问基类成员
数据成员 派生类同名数据成员隐藏基类成员 基类名::成员名
成员函数 派生类同名函数隐藏基类所有同名函数 基类名::函数名()
静态成员 同样适用同名隐藏规则 基类名::成员名

7.2 注意事项总结

cpp 复制代码
// 1. 同名隐藏不受返回类型影响
class Object {
    int getValue() { return 0; }
};
class Base : public Object {
    double getValue() { return 0.0; }  // 隐藏了 Object::getValue
};

// 2. 同名隐藏不受参数列表影响
//    只要函数名相同,基类的所有重载版本都会被隐藏

// 3. 可以通过 using 声明将基类函数引入派生类作用域
class Base : public Object {
public:
    using Object::func;   // 将基类的 func 引入派生类
    void func(int x) { }  // 现在 func() 和 func(int) 都可以访问
};
相关推荐
z落落1 小时前
C# Task WaitAll、WaitAny、WhenAll、WhenAny
开发语言·c#
兰令水1 小时前
hot100【acm版】【2026.7.11/12打卡-java版本】
java·开发语言·数据结构·算法·职场和发展
从零开始的代码生活_1 小时前
C++ string 详解:常用接口、字符串算法与深拷贝实现
开发语言·c++·后端·学习·算法
m0_738120722 小时前
PHP代码审计基础——面向对象(四)
android·开发语言·网络·安全·github·php
2601_963771372 小时前
10 Best PHP Media CMS and Scripts for Web Creators in 2026
开发语言·前端·php
阿里嘎多学长2 小时前
2026-07-09 GitHub 热点项目精选
开发语言·程序员·github·代码托管
带娃的IT创业者2 小时前
监控并非安全:当隐私成为技术的祭品
java·开发语言·安全·数据安全·监控·隐私保护·加密技术
玖玥拾3 小时前
C# 语言进阶(十四)Unity UI界面开发 + 网络消息联动
服务器·开发语言·网络·ui·unity·c#·游戏引擎
aaPIXa6223 小时前
C++ 质量前置检查:clang-format 与 clang-tidy 实践指南
开发语言·c++