Jiahonzheng's Blog

C++ 友元

字数统计: 927阅读时长: 3 min
2018/04/06 Share

概述

友元提供了一种 普通函数 或 类成员函数 访问另一个类中的私有或保护成员的机制,从这句话中,我们知道有两种形式的友元:

  • 友元函数:普通函数,可以访问某个类中的私有或保护成员。
  • 友元类:类A 中的成员函数,可以访问 类B 中的私有或保护成员。

特性

  • 优点
    • 提高了程序的运行效率
  • 缺点
    • 破坏了类的封装性和数据透明性

实现

友元函数

友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。

友元函数是在类声明的任何区域声明,可在类内部或外部定义,若在内部定义则必须在声明时就完成定义

友元类

友元类在类声明的任何区域中声明,而定义则在类的外部

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>

class A {
public:
A(int a) : a(a){};

// 在类声明内,声明友元函数
friend int Get_A_a(A& class_A_instance);

// 在类声明内,声明友元类
friend class B;

private:
int a;
};

// 在类声明外,定义友元类
class B {
public:
int Get_A_a(A& class_A_instance) { return class_A_instance.a; }
};

// 在类声明外,定义友元函数(也可在类内部定义)
int Get_A_a(A& class_A_instance) {
// 通过对象名访问私有或保护成员
return class_A_instance.a;
}

int main() {
A class_A_instance(1);
B class_B_instance;

// 友元函数只是个普通函数,可在任意地方调用
// 输出: 1
std::cout << Get_A_a(class_A_instance) << std::endl;

// 输出: 1
std::cout << class_B_instance.Get_A_a(class_A_instance) << std::endl;

return 0;
}

注意

友元关系没有继承性

类B类A 的友元,类C 继承于 类A ,那么 类B 是不能直接访问 类C 的私有或保护成员。

事实上,考虑这样的情况:若 类B类A 的友元,类C 继承于 类B ,那么 类C 是对 类A 的私有或保护成员的访问情况是怎么样的呢。下面,给出这种情况的代码示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>

class A {
public:
A() : a_private_data(1){};
friend class B;

private:
int a_private_data;
};

class B {
public:
void GetA_B_Public(A &a) {
// ok: B 为 A 的友元类,实现对 A 的私有或保护成员的访问
std::cout << a.a_private_data << std::endl;
}

protected:
void GetA_B_Protected(A &a) {
// ok: B 为 A 的友元类,实现对 A 的私有或保护成员的访问
std::cout << a.a_private_data << std::endl;
}
};

class C : public B {
public:
// ok: 委托父类,实现对 A 的私有或保护成员的访问
void GetA_C_Public(A &a) {
// 也可写成: GetA_B_Protected(a);
B::GetA_B_Protected(a);
}

// error: 友元关系不具备继承性,故 C 不能访问 A 的私有或保护成员
void Wrong(A &a) { std::cout << a.a_private_data << std::endl; }
};

int main() {
A a;
B b; // B 为 A 的友元类
C c; // C 为 B 的派生类

// ok: B 为 A 的友元类,实现对 A 的私有或保护成员的访问
// 输出: 1
b.GetA_B_Public(a);

// ok: C 调用父类 B 的方法,实现对 A 的私有或保护成员的访问
// 输出: 1
c.GetA_B_Public(a);

// ok: C 通过委托父类,实现对 A 的私有或保护成员的访问
// 输出: 1
c.GetA_C_Public(a);

return 0;
}

友元关系没有传递性

类B类A 的友元,类C类B 的友元,那么 类C 是不能直接访问 类A 的私有或保护成员,即不存在“友元的友元”的关系。

原文作者:Jiahonzheng

原文链接:https://blog.jiahonzheng.cn/2018/04/06/C++ 友元/

发表日期:April 6th 2018

更新日期:November 26th 2019

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

CATALOG
  1. 1. 概述
  2. 2. 特性
  3. 3. 实现
    1. 3.1. 友元函数
    2. 3.2. 友元类
    3. 3.3. 代码示例
  4. 4. 注意
    1. 4.1. 友元关系没有继承性
    2. 4.2. 友元关系没有传递性