目录
一、基本概念
在继承体系中,基类和派生类拥有各自独立的作用域。当派生类与基类中存在同名成员时,派生类成员会屏蔽对基类同名成员的直接访问,这种情况称为隐藏(Hide)或重定义(Redefinition)。
二、成员变量隐藏示例
以下代码展示了成员变量的隐藏现象:
#include <iostream>
#include <string>
using namespace std;
// 基类
class Person {
protected:
int _num = 111; // 身份编号
};
// 派生类
class Student : public Person {
public:
void fun() {
cout << _num << endl; // 访问的是Student类的_num
}
protected:
int _num = 999; // 学号
};
int main() {
Student s;
s.fun(); // 输出:999
return 0;
}
若要访问基类中的同名成员,需使用作用域限定符(::
)显式指定:
void fun() {
cout << Person::_num << endl; // 输出:111(访问基类的_num)
}
三、成员函数隐藏
成员函数的隐藏只需函数名相同即可构成,与参数列表无关:
例如,对于以下代码,调用成员函数fun时将直接调用子类当中的fun,若想调用父类当中的fun,则需使用作用域限定符指定类域。
#include <iostream>
#include <string>
using namespace std;
// 基类
class Person {
public:
void fun(int x) {
cout << x << endl;
}
};
// 派生类
class Student : public Person {
public:
void fun(double x) { // 与基类fun函数构成隐藏
cout << x << endl;
}
};
int main() {
Student s;
s.fun(3.14); // 调用Student::fun(double)
s.Person::fun(20); // 调用Person::fun(int)
return 0;
}
重要提示:
基类与派生类中的fun
函数不构成函数重载,因为函数重载要求在同一作用域内。为避免混淆,在继承体系中应尽量避免定义同名成员。
四、总结说明
继承体系中基类和派生类拥有独立作用域
派生类与基类同名成员构成隐藏关系,派生类成员屏蔽基类成员的直接访问
可使用
基类::基类成员
语法显式访问被隐藏的基类成员成员函数只需函数名相同即构成隐藏,与参数类型和数量无关
实际开发中应尽量避免在继承体系中定义同名成员
五、典型示例
#include <iostream>
#include <string>
using namespace std;
class Person {
protected:
string _name = "小李";
int _num = 111; // 身份证号
};
class Student : public Person {
public:
void Print() {
cout << "姓名:" << _name << endl;
cout << "身份证号:" << Person::_num << endl; // 显式访问基类成员
cout << "学号:" << _num << endl; // 访问派生类成员
}
protected:
int _num = 999; // 学号(与基类_num构成隐藏)
};
int main() {
Student s1;
s1.Print();
return 0;
}
六、相关选择题讲解
1、下面代码中的A和B类中的两个func构成什么关系()
答案:B.隐藏
解析:虽然函数签名不同,但因处于不同作用域且函数名相同,构成隐藏关系而非重载。
知识回顾:函数签名(Function Signature)
函数签名是编译器用于区分不同函数的一个唯一标识。它主要由以下部分组成:
函数名
参数列表(参数的类型、数量和顺序)
特别注意:函数的返回类型不属于函数签名的一部分。
2、下面程序的编译运行结果是什么()
答案:A.编译报错
解析:b.fun()
调用会产生编译错误,因为派生类的fun(int)
隐藏了基类的fun()
,而b.fun()
找不到无参版本。需要使b.A::fun()
显式调用基类函数。
class A {
public:
void fun() {
cout << "func()" << endl;
}
};
class B : public A {
public:
void fun(int i) { // 隐藏了A::fun()
cout << "func(int i)" << i << endl;
}
};
int main() {
B b;
b.fun(10); // 正确:调用B::fun(int)
b.fun(); // 错误:A::fun()被隐藏
b.A::fun(); // 正确:显式调用基类函数
return 0;
}