友元的作用与边界

目录

[1. 正常情况:private 外人碰不到](#1. 正常情况:private 外人碰不到)

[2. 加上 friend:给 foo 发"内部通行证"](#2. 加上 friend:给 foo 发“内部通行证”)

[3. 也可以给"整个类"发通行证](#3. 也可以给“整个类”发通行证)

[4. 友元的边界(很容易误会)](#4. 友元的边界(很容易误会))

[5. 为什么要用 friend?(两个典型原因)](#5. 为什么要用 friend?(两个典型原因))

[场景 1:运算符重载(特别是对称的 operator<<, operator+)](#场景 1:运算符重载(特别是对称的 operator<<, operator+))

[场景 2:两个类需要"互相知道内部细节"](#场景 2:两个类需要“互相知道内部细节”)

[6. 为什么说"不要滥用"?](#6. 为什么说“不要滥用”?)


先别管那些"协作""耦合"大词,我们用一句大白话先定个性质:

friend = 把"本来进不来的人",临时拉进自己家里,让 TA 也能碰你的私有成员。

也就是说:
友元 = 特殊通行证,允许别的函数/类访问你类的 private / protected 成员。


1. 正常情况:private 外人碰不到

复制代码
class A {
private:
    int x = 42;
};

void foo(A& a) {
    // a.x; // ❌ 编译不过,x 是 private
}

外部函数 foo 正常情况下是没资格访问 A::x 的。


2. 加上 friend:给 foo 发"内部通行证"

复制代码
class A {
    friend void foo(A&);  // 声明:foo 是我的友元
private:
    int x = 42;
};

void foo(A& a) {
    // 现在可以直接访问 private 成员了
    a.x = 100;   // ✅ 合法,因为 foo 是 A 的 friend
}
  • friend void foo(A&); 的意思就是:

    "我,A,允许 foo 这个函数看到我的 private / protected。"


3. 也可以给"整个类"发通行证

复制代码
class B; // 前向声明

class A {
    friend class B;  // 整个 B 类都是我的朋友
private:
    int x = 42;
};

class B {
public:
    void change(A& a) {
        a.x = 10;    // ✅ 合法,因为 B 是 A 的 friend
    }
};
  • friend class B; 的意思是:

    "B 这个类里的所有成员函数,都可以访问 A 的私有东西。"


4. 友元的边界(很容易误会)

  1. 友元 ≠ 成员

    • foo 虽然能访问 A 的私有成员,但它依然是"外面"的函数,不是 A 的成员函数。
  2. 友元关系不传递

    • A 把 B 设为 friend

    • B 再把 C 设为 friend

    • 并不代表 C 是 A 的 friend

    • 关系只在"谁写了 friend 声明"的那个类里生效

  3. 友元关系不继承

    • A 声明 friend class B;

    • B 只能访问 A 的私有

    • A 的子类(比如 class AChild : public A {})的私有,B 还是不能碰


5. 为什么要用 friend?(两个典型原因)

场景 1:运算符重载(特别是对称的 operator<<, operator+

复制代码
class Vec2 {
    friend std::ostream& operator<<(std::ostream& os, const Vec2& v);
public:
    Vec2(int x, int y) : x(x), y(y) {}
private:
    int x, y;
};

std::ostream& operator<<(std::ostream& os, const Vec2& v) {
    // 可以访问 v.x, v.y 虽然它们是 private
    return os << "(" << v.x << ", " << v.y << ")";
}

场景 2:两个类需要"互相知道内部细节"

比如容器和迭代器,迭代器需要访问容器的内部数组指针等,这时用 friend 简化。


6. 为什么说"不要滥用"?

因为:

  • 写多了 friend,就等于到处打洞,让很多外部东西都能直接碰你的 private

  • 封装性变差,类之间关系变得很紧,代码不好维护

一般建议

只在确实需要共享内部细节的少数地方用 friend,比如:

  • 运算符重载函数

  • 明确是"内部实现用"的辅助类/函数(如 Impl, Iterator


如果一句话再总结:

friend 就是:"我信任你,给你看我原本不想给别人看的内部实现"------强大但要少用。

相关推荐
Gigavision36 分钟前
基于BUAA-MIHR数据集的噪声解耦对比学习算法
人工智能·python·深度学习·算法
鹿角片ljp1 小时前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
彧azz2 小时前
算法设计与分析:贪心与动态规划
数据结构·学习·算法·贪心算法·动态规划
Beyond_System|系统之外3 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
漂流瓶jz5 小时前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
叠层归一研究院6 小时前
基于极限自指的叠层归一宇宙结构理论——无元外部封闭系统的内生区分模型
人工智能·经验分享·算法·agi
Selvaggia7 小时前
Diffusion Model 的基本原理与模型架构
算法
wabs6668 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
hanlin038 小时前
刷题笔记:力扣第41题-缺失的第一个正数
笔记·算法·leetcode
shehuiyuelaiyuehao9 小时前
算法50,分治归并,数组中的逆序对
java·算法