C++ 友元函数

2025 年 8 月 29 日 | 阅读 10 分钟

在 C++ 中,友元函数是一种非成员函数,它可以访问类的私有(private)和保护(protected)成员。该函数在类内部使用 `friend` 关键字声明为友元。如果希望将某个函数声明为友元函数,类可以授予它特殊的访问权限,从而使其能够操作类内部的数据。

C++ 中,友元可以是函数、成员函数、类或类模板,以及函数模板。在这种情况下,整个类和类中的所有成员都将成为友元。

C++ 友元函数语法

它具有以下语法:

友元函数可以像普通 C++ 函数一样定义在程序的任何部分。函数定义不使用 `friend` 关键字或 作用域解析运算符

C++ 友元函数示例

我们以一个使用友元函数打印盒子长度的例子来说明。

示例

编译并运行

输出

Length of the box: 10

说明

在此示例中,我们创建了一个 `Box` 类,其中包含一个私有整数成员 `length`,并将其初始化为 0。之后,在类内部声明了一个友元函数 `printLength()`。

在 `printLength()` 函数中,盒子长度增加了 10 并返回。在 `main()` 函数中,创建 `Box` 类的对象 `b` 并将其传递给 `printLength()`,该函数会将更新后的长度(10)打印到控制台。

访问私有和保护成员

在 C++ 中,私有和保护成员在类外部是无法访问的。如果需要访问这些成员,我们可以利用友元函数。友元函数使我们能够直接访问类的私有和保护成员。

访问私有和保护成员示例

我们通过一个示例来说明 C++ 中的私有和保护成员。

示例

编译并运行

输出

Accessing Private: 25
Accessing Protected: 50

说明

在此示例中,我们创建了一个 `Tpoint` 类,它有两个数据成员 `private_memb` 和 `protected_memb`,它们在构造函数中初始化。之后,在类内部声明了一个 `friendFunction`,但将其定义在类外部。在 `main()` 函数中,`Tpoint` 类的对象展示了友元函数如何提供对其他无法访问的类成员的受控访问。

友元函数的类型

Friend Function in C++

友元函数主要可以分为两类。

  • 非成员友元函数
  • 另一个类的成员函数

非成员友元函数

在 C++ 中,非成员友元函数在类中声明,但这些函数不是类成员。它允许访问类的私有和保护成员。这些非成员函数通常用于提供能够操作类私有数据成员的外部函数。

C++ 非成员友元函数示例

我们以一个示例来演示 C++ 中的非成员友元函数。

示例

编译并运行

输出

Private Data: 57
Protected Data: 18

说明

在此示例中,`friend_Funct` 函数修改并显示 `Tpoint` 类对象的 `private_data` 和 `protected_data`,即使这些成员在类外部是无法访问的。

另一个类的成员函数

在 C++ 中,另一个类的成员函数可以被声明为友元函数。这使得友元函数可以访问另一个类的私有和保护成员。

当需要两个类紧密协作时,例如在 运算符重载 或需要直接访问内部数据的实用函数中,这非常有用。

C++ 另一个类成员函数示例

我们通过一个示例来说明 C++ 中另一个类成员函数的例子。

示例

编译并运行

输出

Private value of class First accessed from class Last: 115

说明

在此示例中,`First` 类有一个私有成员 `val`,而 `Last` 类包含一个成员函数 `showValue(First)`。之后,该函数在 `First` 中被声明为友元,从而使其能够访问 `val`。在 `main()` 函数中,`y.showValue(x)` 函数演示了通过友元成员函数进行的跨类私有访问。

友元函数的使用

C++ 中友元函数的几种用途如下:

1) 使用友元函数访问多个类

如果我们想在 C++ 中访问多个类的私有数据,友元函数将非常有用。

多个类的友元函数示例

我们以一个示例来演示多个类的友元函数。

示例

编译并运行

输出

10

说明

在此示例中,我们演示了使用友元函数访问多个类的私有数据成员。在 `min` 方法中,比较两个类的数值,并打印出较小的值。之后,`main()` 函数为两个对象设置值并调用友元函数来显示最小值。

2) 使用友元函数进行运算符重载

在 C++ 中,当运算符的左侧操作数不是该类的对象时(例如 +、-、* 等运算符),可以使用友元函数来重载类的运算符。

友元函数不是类的成员,但它们可以访问类的私有和保护成员。这些函数适用于运算符重载,当需要从类外部直接访问内部数据时。

C++ 使用友元函数进行运算符重载示例

我们以一个示例来演示 C++ 中使用友元函数进行运算符重载。

示例

编译并运行

输出

The Result is: 8+i5 + 20+i7 = 28+i12

说明

在此示例中,我们在 `Cmplex_num()` 类中定义了两个整数 `real` 和 `imag`。在 `void show()` 函数中,我们使用一个临时变量,并进行运算符重载以执行加法运算。在 `main()` 函数中,`cout` 函数显示输出。

友元函数特性

C++ 中友元函数的几项特性如下:

  • 声明为友元的函数不在该类的作用域内。
  • 它不能使用对象来调用,因为它不在该类作用域内。
  • 它可以像普通函数一样调用,无需使用对象。
  • 它可以声明在类的私有部分或公有部分。

C++ 友元类

在 C++ 中,友元类被授予访问声明其为友元的类的私有和保护成员的权限。如果一个类声明另一个类为程序中的友元,则第二个类可以访问第一个类的私有和保护成员。

当我们声明一个类为友元类时,友元类的所有成员函数都成为友元函数。这与友元函数类似。

语法

它具有以下语法:

C++ 友元类示例

我们通过一个示例来说明 C++ 中的友元类。

示例

编译并运行

输出

The Value of i is: 10

说明

在此示例中,`First` 类包含一个初始化为 10 的私有整数成员 `i`。`Last` 类通过 `friend class Last` 语句声明为 `First` 的友元,这使 `Last` 能够访问 `First` 的私有成员。在 `main()` 函数中,创建了两个类的对象,并调用 `display()` 函数来输出 `First` 类的私有数据。

C++ 友元函数的优缺点

C++ 友元函数的几项优点和缺点如下。

友元函数的优点

  • 访问私有成员:友元函数由于能够访问类的受保护和私有成员,因此可以方便地修改它们,从而提供了更多的设计灵活性。
  • 运算符重载:由于能够访问相关对象的私有数据,它们也经常用于运算符重载。
  • 关注点分离:借助友元函数,可以将用户界面与实际实现分离,从而提高了代码的组织性。
  • 性能提升:友元函数允许访问类的私有部分,减少了 getter/setter 函数的使用,从而提高了效率。
  • 类间通信:它们允许不同的类在不需要直接关系的情况下进行通信,这在复杂设计中有益。

友元函数的缺点

  • 封装破坏:友元函数可以访问私有成员,从而违反了封装原则,使得代码维护成为一项复杂任务。
  • 紧耦合:友元函数使类相互依赖,这使得设计模块化变得困难。
  • 安全风险:在 C++ 中,使用友元函数和友元类允许访问私有数据可能给类带来潜在风险。

C++ 友元函数选择题

1) C++ 中的友元函数是什么?

  1. 不允许访问任何类成员的函数。
  2. 可以访问所有类成员(包括 public、private 和 protected)的函数。
  3. 只允许访问类公共成员的函数。
  4. 允许访问公共和受保护类成员的函数。
 

答案:b) 可以访问所有类成员(包括 public、private 和 protected)的函数。


2) 在 C++ 中,友元函数可以成为另一个类的成员吗?

  1. 是的
  2. 不能
  3. 仅当声明为 public 时
  4. 仅当两个类都继承时
 

答案:a) 是


3) 在 C++ 中,定义友元函数使用哪个关键字?

  1. 朋友
  2. extern
  3. friend
  4. private
 

答案:c) friend


4) 以下代码的输出是什么?

  1. 10
  2. 编译错误
  3. 20
  4. 链接器错误
 

答案:c) 20


5) 关于 C++ 中的友元函数,以下哪个陈述是正确的?

  1. 友元函数在类作用域内。
  2. 它们只能访问公共成员。
  3. 它们只能使用类对象调用。
  4. 友元函数不在类作用域内。
 

答案:d) 友元函数不在类作用域内。


下一主题C++ this 指针