# 友元函数

URL: https://caijiao.org/cpp/oop/friend
Source: docs/cpp/oop/friend.md
Description: 本节介绍 C++ 中的友元函数。友元函数允许访问类的私有成员和保护成员，而不需要成为该类的成员函数。通过友元函数，可以方便地在不破坏封装性的情况下进行类的内部操作。

在 C++ 中，友元函数（`friend` function）是一种特殊的函数，它能够访问类的私有成员（`private`）和保护成员（`protected`），即使该函数并不是该类的成员函数。友元函数的主要作用是为了方便不同类之间的协作，或在实现某些特定功能时提供必要的访问权限。

## 友元函数的特性

- **非成员函数**：友元函数通常是类外部的普通函数，尽管它能够访问类的私有和保护成员。
- **可以是类外部的函数**：友元函数可以是全局函数，也可以是其他类的成员函数。
- **声明方式**：友元函数必须在类内部通过 `friend` 关键字声明。
- **访问权限**：友元函数可以访问类的所有成员，包括私有和保护成员。

## 如何定义友元函数

友元函数通过在类定义内部使用 `friend` 关键字进行声明。声明后，友元函数就能访问该类的所有成员。

### 示例：友元函数的定义与使用

```cpp
#include <iostream>
using namespace std;

class Box {
private:
    int length;

public:
    Box(int len) : length(len) {}

    // 声明一个友元函数
    friend void printLength(Box& box);
};

// 友元函数定义
void printLength(Box& box) {
    cout << "Box Length: " << box.length << endl;
}

int main() {
    Box box(10);
    printLength(box);  // 友元函数可以访问 Box 类的私有成员
    return 0;
}
````

### 输出：

```
Box Length: 10
```

在这个例子中，`printLength` 函数被声明为 `Box` 类的友元函数，因此它能够访问 `Box` 类的私有成员 `length`。

## 友元函数的注意事项

* **访问权限**：友元函数虽然可以访问类的私有和保护成员，但它本身并不是类的成员。
* **作用范围**：友元函数并不继承类的访问权限，它仅对某个特定类有效。
* **不破坏封装性**：使用友元函数时，仍然可以控制对类内部成员的访问，避免过度暴露类的实现细节。

## 友元函数与类的成员函数

* **不同于成员函数**：成员函数是类的一部分，并且它们在类的作用域内定义；而友元函数并不属于类的一部分，尽管它可以访问类的私有成员。
* **可以访问类的私有成员**：成员函数和友元函数都能访问类的私有成员，但成员函数只能在类内部定义，友元函数则可以在类外部定义。

### 示例：友元函数与类成员函数的区别

```cpp
#include <iostream>
using namespace std;

class Box {
private:
    int length;

public:
    Box(int len) : length(len) {}

    // 成员函数
    void displayLength() {
        cout << "Length: " << length << endl;
    }

    // 声明友元函数
    friend void printLength(Box& box);
};

// 友元函数定义
void printLength(Box& box) {
    cout << "Box Length (from friend function): " << box.length << endl;
}

int main() {
    Box box(10);
    box.displayLength();      // 调用成员函数
    printLength(box);         // 调用友元函数
    return 0;
}
```

### 输出：

```
Length: 10
Box Length (from friend function): 10
```

## 友元类

除了友元函数外，C++ 还允许定义友元类。友元类的成员函数也能访问另一个类的私有成员。

### 示例：友元类的定义

```cpp
#include <iostream>
using namespace std;

class Box;

class BoxManager {
public:
    void printLength(Box& box);
};

class Box {
private:
    int length;

public:
    Box(int len) : length(len) {}

    // 声明 BoxManager 为友元类
    friend class BoxManager;
};

// 友元类成员函数定义
void BoxManager::printLength(Box& box) {
    cout << "Box Length (from friend class): " << box.length << endl;
}

int main() {
    Box box(10);
    BoxManager manager;
    manager.printLength(box);  // 友元类的成员函数访问 Box 类的私有成员
    return 0;
}
```

### 输出：

```
Box Length (from friend class): 10
```

## 总结

* 友元函数是 C++ 中的一种特殊函数，它允许非成员函数访问类的私有成员和保护成员。
* 友元函数声明时使用 `friend` 关键字，它并不是类的成员函数，但能像成员函数一样访问类的私有数据。
* 友元函数的使用可以方便地实现类与类之间的协作，但使用时应当注意封装性和访问控制的平衡。
