面试题答案
一键面试友元函数在继承关系下的访问权限
- 类 B 作为类 A 的友元类:
- 类 B 的友元函数可以访问类 A 的私有和保护成员。这是因为友元关系是一种特殊的信任关系,当类 B 被声明为类 A 的友元类时,类 B 及其友元函数被赋予了访问类 A 私有和保护成员的特权。
- 类 C 继承自类 A:
- 友元关系不会被继承。即类 B 的友元函数不能直接访问类 C 的私有和保护成员,即使类 C 继承自类 A。这是因为友元关系是基于特定类的,而不是基于继承层次结构。每个类的友元关系是独立定义的,类 C 不会自动获得类 A 的友元的访问特权。
- 然而,类 B 的友元函数仍然可以通过类 A 的公共接口间接访问类 C 从类 A 继承来的公有成员。例如,如果类 A 有一个公有函数
getPrivateData()
来返回其私有成员数据,类 B 的友元函数可以通过类 C 的对象调用getPrivateData()
来间接访问类 C 从类 A 继承的相关私有数据(如果类 A 提供了这样的接口)。
类 C 中重新定义同名私有成员的访问情况
如果在类 C 中重新定义了一个与类 A 中同名的私有成员:
-
类 B 的友元函数不能直接访问类 C 新定义的这个同名私有成员。因为友元关系不继承,类 B 的友元函数只对类 A 的成员有访问特权,对类 C 新定义的私有成员没有访问权限。
-
类 B 的友元函数仍然可以访问类 A 中的同名私有成员(前提是通过类 A 的对象或指向类 A 对象的指针/引用)。这是因为其友元关系针对的是类 A,只要能获取到类 A 相关的访问对象,就可以访问类 A 的私有成员。
例如:
#include <iostream>
class A {
private:
int data;
friend class B;
public:
A(int d) : data(d) {}
};
class B {
public:
void accessA(A& a) {
std::cout << "Accessing A's private data: " << a.data << std::endl;
}
};
class C : public A {
private:
int data; // 与类 A 中的 data 同名
public:
C(int d1, int d2) : A(d1), data(d2) {}
};
int main() {
A a(10);
B b;
b.accessA(a);
C c(20, 30);
// b.accessA(c); // 错误,类 B 的友元函数不能直接访问类 C 的新私有成员 data
return 0;
}
在上述代码中,B
类的 accessA
函数可以访问 A
类的 data
,但不能直接访问 C
类新定义的 data
。