C++中的友元(friend)函数和类是什么?C++ friend用法详解【突破封装】

8次阅读

友元是 C ++ 中唯一被明确允许打破封装限制的机制,通过主动授权使非成员函数或类访问私有 / 保护成员;友元函数需在类内用 friend 声明、类外定义(不加 friend),无 this 指针;友元类的所有成员函数均可访问被授权类的私有 / 保护成员,但关系不传递、不继承、单向;常用于流操作符重载等需外部函数深度协同的场景。

C++ 中的友元(friend)函数和类是什么?C++ friend 用法详解【突破封装】

友元不是类的成员,但它能访问类的私有(private)和保护(protected)成员——这是 C ++ 中 ** 唯一被明确允许打破封装限制的机制 **,但不破坏类的设计意图,关键在于“主动授权”。

friend 函数:外部函数获得类内部访问权

在类内部用 friend 关键字声明一个普通函数(可以是全局函数,也可以是其他类的成员函数),该函数就成为当前类的友元。它定义在类外,不占用类的对象内存,也不受 public/private/protected 访问限定符影响。

常见写法:

  • 声明时加friend,定义时 ** 不加 **(否则编译报错)
  • 友元函数参数通常包含类对象的引用或指针,否则无法操作具体实例
  • 它没有 this 指针,所有访问都需显式通过对象名

示例:

立即学习C++ 免费学习笔记(深入)”;

class Box {private:     double width = 10.5;     friend void printWidth(const Box& b); // 声明为友元 };  void printWidth(const Box& b) {// 定义:不写 friend!std::cout << "Width:" << b.width << 'n'; // ✅ 可直接访问 private 成员}

friend 类:整个类的所有成员函数都是友元

把一个类声明为另一个类的friend,意味着这个“友元类”的 ** 所有成员函数 **(包括后续新增的)都能访问被授权类的私有与保护成员。

注意点:

  • 友元关系 ** 不具有传递性 **:A 是 B 的友元,B 是 C 的友元,不代表 A 是 C 的友元
  • 友元关系 ** 不具有继承性 **:基类的友元不会自动成为派生类的友元
  • 友元关系 ** 是单向的 **:声明 friend class B; 只让 B 访问当前类,不代表当前类能访问 B 的私有成员

典型用途:容器类与迭代器类配合、紧密耦合的辅助类(如 std::string 和它的私有字符缓冲管理类)。

友元函数作为重载操作符的常用场景

很多二元操作符(如 >>+==)需要左操作数是其他类型(比如std::ostream),无法定义为成员函数(否则this 会强制占左边)。这时用 friend 函数最自然。

例如流输出重载:

class Point {private:     int x, y; public:     Point(int x=0, int y=0) : x(x), y(y) {}     friend std::ostream& operator<<(std::ostream& os, const Point& p) {os << "(" << p.x << "," << p.y << ")"; // ✅ 访问 private 成员         return os;     } };

调用 std::cout 就能正常工作——因为operator 是std::ostream 的成员函数,而 Point 主动授予它访问权限。

使用 friend 的注意事项和替代思路

friend本质是“可控的破窗”,用不好会削弱封装价值。优先考虑以下替代方式:

  • 提供 publicgetter/setter接口(适合简单 数据访问
  • 把逻辑移到类内部,设计更合理的成员函数(推荐)
  • 用嵌套类(class Inner定义在 class Outer 内部),嵌套类天然可访问外围类的私有成员

只有当外部函数 / 类 ** 确实需要深度协同且无法合理重构 ** 时,再用 friend。例如:两个类共享底层数据结构、序列化 工具、调试打印器等。

基本上就这些。friend 不是后门,而是接口契约的一部分——你主动签了字,才允许别人进你的房间。

星耀云
版权声明:本站原创文章,由 星耀云 2025-12-30发表,共计613字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources