0

0

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

穿越時空

穿越時空

发布时间:2025-12-30 10:10:03

|

193人浏览过

|

来源于php中文网

原创

友元是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和它的私有字符缓冲管理类)。

Winston AI
Winston AI

强大的AI内容检测解决方案

下载

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

很多二元操作符(如>>+==)需要左操作数是其他类型(比如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不是后门,而是接口契约的一部分——你主动签了字,才允许别人进你的房间。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

311

2023.08.02

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

529

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

4

2025.12.22

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

988

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

48

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

134

2025.12.29

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

455

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

6

2025.12.06

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.1万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号