欢迎光临
我们一直在努力

同名隐藏基础

同名隐藏

一、什么是同名隐藏?

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

class Object {
public:
int value;
int num; // 基类成员
};

class Base : public Object {
public:
int num; // 派生类成员(与基类同名!)
int sum;

void fun() {
num = 10; // 默认访问派生类自己的 num
// 基类的 num 被隐藏了
}
};

二、同名隐藏的核心规则

2.1 就近原则

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

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 如何访问被隐藏的基类成员?

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

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 基本示例

#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 访问权限对同名隐藏的影响

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 函数同名隐藏

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

class Object {
public:
void func() { } // 函数1
void func(int) { } // 函数2(重载)
};

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

五、完整代码示例

#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
函数名相同 是 是
参数相同 不一定 必须完全相同
作用 隐藏基类所有同名函数 实现多态
基类函数可见性 被隐藏(需要 :: 访问) 可被覆盖,仍可通过基类指针访问
多态行为 不支持 支持

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 注意事项总结

// 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) 都可以访问
};

赞(0)
未经允许不得转载:171主机测评 » 同名隐藏基础
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址