接帮人家做网站的网站/企业整站seo
一、引言
在C++中,友元函数(Friend Function)是一个独特而强大的特性,它打破了类的封装性,允许一个或多个非成员函数访问类的私有(private)和保护(protected)成员。尽管这种特性在某些情况下可能引发争议,因为它违反了面向对象编程中的封装原则,但在需要高效访问类内部状态或实现某些特定设计时,友元函数却又非常适用。
1.1 封装与友元函数的关系
在面向对象编程(OOP)中,封装是一种将数据(属性)与操作这些数据的函数(方法)绑定在一起的方法。封装的主要目的是隐藏类的内部实现细节,只对外提供有限的接口供外部使用。然而,在某些情况下,我们可能希望允许某些特定的非成员函数访问类的私有成员。这时,友元函数就显得尤为重要了。
1.2 友元函数的概念
友元函数不是类的成员函数,但它可以访问类的所有私有(private)和保护(protected)成员。要使一个函数成为类的友元,需要在类定义中声明该函数为友元。友元函数可以是普通函数,也可以是其他类的成员函数。
二、友元函数的定义与使用
2.1 定义友元函数
在类定义中,使用friend关键字可以声明一个或多个友元函数。友元函数的声明可以放在类的任何位置(但通常放在类定义的开始部分),但它们的定义(实现)必须在类定义之外进行。
示例:
#include <iostream> class MyClass {
private: int value; public: MyClass(int val) : value(val) {} // 声明友元函数 friend void printValue(const MyClass& obj);
}; // 定义友元函数
void printValue(const MyClass& obj) { std::cout << "Value: " << obj.value << std::endl;
} int main() { MyClass myObj(10); printValue(myObj); // 输出: Value: 10 return 0;
}
在上面的示例中,printValue函数被声明为MyClass的友元函数,因此它可以访问MyClass对象的私有成员value。
2.2 友元函数的特性
非成员函数:友元函数不是类的成员函数,因此它不会隐式地接收类的this指针。
访问权限:友元函数可以访问类的所有成员,包括私有和保护成员。
作用域:友元函数的作用域不是类的作用域,而是定义它的作用域。但是,它可以通过类的对象来访问类的成员。
数量不限:一个类可以有任意数量的友元函数。
不继承:友元关系不是继承的。如果类B是类A的友元,那么类B的子类不会自动成为类A的友元。
2.3 友元成员函数
除了普通函数外,类的成员函数也可以被声明为其他类的友元函数。这允许一个类的成员函数访问另一个类的私有成员。
示例:
#include <iostream> class MyClassB; // 前向声明 class MyClassA {
private: int value; public: MyClassA(int val) : value(val) {} // 声明MyClassB的成员函数为友元 friend void MyClassB::printValue(const MyClassA& obj);
}; class MyClassB {
public: void printValue(const MyClassA& obj) { std::cout << "Value from MyClassA: " << obj.value << std::endl; }
}; int main() { MyClassA myObjA(20); MyClassB myObjB; myObjB.printValue(myObjA); // 输出: Value from MyClassA: 20 return 0;
}
注意,在声明友元成员函数时,需要先对目标类进行前向声明,因为编译器在解析MyClassA的类定义时需要知道MyClassB是一个类名。
三、友元函数的使用场景
3.1. 重载操作符
友元函数最常见的用途之一是用于重载操作符,特别是当操作符需要访问类的私有或保护成员时。例如,在自定义的复数类(Complex)中,你可能想要重载<<操作符以便能够直接将复数对象输出到流中。由于输出操作需要访问复数对象的实部和虚部(这些通常是私有成员),因此将<<操作符定义为复数类的友元函数是一个很好的选择。
3.2. 辅助函数
有时,我们可能需要一些辅助函数来帮助实现类的功能,但这些函数并不适合作为类的成员函数。例如,如果有一个表示二维图形的类(如圆形或矩形),我们可能需要一个函数来计算两个图形是否相交。这样的函数可能需要访问图形的私有成员(如中心坐标和半径或边界),但将这些功能作为类的成员函数可能并不合适,因为它们并不是图形对象本身的操作。这时,可以将这些辅助函数声明为类的友元函数。
3.3. 模板类中的友元
在模板类中,友元函数的使用变得更加复杂但也更加有用。模板类的友元可以是另一个模板类或非模板类,甚至可以是模板函数。这允许模板类与非模板代码或不同类型的模板代码之间进行更紧密的交互。例如,你可能有一个模板容器类,并希望提供一个模板化的友元函数来执行某种类型的算法,这个算法需要访问容器的内部数据结构。
3.4. 访问控制绕过
虽然这通常不是推荐的做法,但在某些特殊情况下,友元函数可以用来绕过类的访问控制,以提供对私有成员的访问。这可以在需要优化性能(如避免通过公共接口访问时产生的额外开销)或实现特定设计模式(如访问者模式)时非常有用。然而,过度使用友元可能会破坏封装性,使代码更难理解和维护。
3.5. 跨类访问
友元函数还可以用于实现跨类访问,即一个类的友元函数可以访问另一个类的私有成员。这在设计需要紧密协作的类时特别有用,例如,在某些设计模式(如代理模式或装饰器模式)中,一个类的行为可能依赖于另一个类的内部状态。
相关文章:

C++学习笔记-友元函数的定义与使用
一、引言 在C中,友元函数(Friend Function)是一个独特而强大的特性,它打破了类的封装性,允许一个或多个非成员函数访问类的私有(private)和保护(protected)成员。尽管这…...

熵、交叉熵、KL散度
这里写目录标题 熵KL散度引入交叉熵。交叉熵的二分类公式: 再次理解SoftMax函数结束 熵 熵,是一个物理上的概念,表示一个系统的不确定性程度,或者表示一个系统的混乱程序。 下边是信息熵的演示: 信息熵的公式如下&…...

THS配置keepalive(yjm)
启动完THS管理控制台和THS后,登录控制台,进入实例管理》节点管理,可以分别使用界面配置和编辑配置设置长连接。 1、界面配置 点击界面配置》集群设置,启用长连接,设置长连接数、最大请求数和超时时间。 2、编辑配置 …...

新加坡裸机云多IP服务器特性
新加坡裸机云多IP服务器是一种高性能、稳定性强,且具备多IP地址特性的服务器。它主要适用于需要高度计算性能、网络连接稳定和高安全性的业务场景,如跨境外贸等。下面将详细探讨该类型服务器的特性,rak部落为您整理发布新加坡裸机云多IP服务器…...

深入理解ADB:Android调试桥详解与使用指南
🍎个人博客:个人主页 🏆个人专栏:Android ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 1. 什么是ADB? ADB的基本原理: 2. ADB的安装与配置 安装ADB工具集: 配置ADB环境变量&am…...

PACS-医学影像信息管理系统,全影像科室PACS源码,内置包括MPR、CMPR、VR等三维处理功能
PACS系统可以覆盖医院现有放射、CT、MR、核医学、超声、内镜、病理、心电等绝大部分DICOM和非DICOM检查设备,支持从科室级、全院机、集团医院级乃至到区域PACS的平滑扩展,能够与医院HIS、集成平台的有效集成和融合,帮助医院实现了全院医学影像…...

无人机搭载无人机反制设备可行性分析
一、引言 随着无人机技术的飞速发展,无人机在各个领域的应用越来越广泛。然而,无人机的不当使用也可能带来安全隐患和隐私问题。因此,无人机反制设备应运而生,用于对非法或危险无人机进行干扰和控制。本文将对无人机搭载无人机反…...

MATLAB绘制方波、锯齿波、三角波、正弦波和余弦波、
一、引言 MATLAB是一种具有很强的数值计算和数据可视化软件,提供了许多内置函数来简化数学运算和图形的快速生成。在MATLAB中,你可以使用多种方法来快速绘制正弦波、方波和三角波。以下是一些基本的示例,展示了如何使用MATLAB的命令来实现正弦…...

【通信协议-RTCM】MSM语句(2) - RINEXMSM7语句总结(重要!自动化开发计算卫星状态常用)
注释: 在工作中主要负责的是RTCM-MSM7语句相关开发工作,所以主要介绍的就是MSM7语句相关内容 1. 相位校准参考信号 2. MSM1、MSM2、MSM3、MSM4、MSM5、MSM6和MSM7的消息头内容 DATA FIELDDF NUMBERDATA TYPENO. OF BITSNOTES Message Number - 消息编…...

ios CCUIFont.m
// // CCUIFont.h // CCFC // //#import <Foundation/Foundation.h>// 创建字体对象 #define CREATE_FONT(fontSize) [UIFont systemFontOfSize:(fontSize)]interface UIFont(cc) (void)logAllFonts;end // // CCUIFont.m // CCFC // //#import "CCUIFont.h&…...

调度子系统在特定时间执行
时序逻辑调度器设计模式允许您安排Simulink子系统在指定时间执行。以下模型说明了这种设计模式。 时序逻辑调度器图表包含以下逻辑: 时序逻辑调度器的关键行为 时序逻辑调度器图表包含两个状态,它们以不同的速率调度函数调用子系统A1、A2和A3的执行&…...

【QAC】Dashboard服务端如何配置
【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决Dashboard服务端如何配置的问题。 2、 问题场景 客户想使用Dashboard,Dashboard服务端如何配置。 3、软硬件环境 1、软件版本:HelixQAC23.04 2、机器环境:Windows 64bit 3…...

深入理解Linux网络(四):TCP接收阻塞
TCP socket 接收函数 recv 发出 recvfrom 系统调用。 进⼊系统调⽤后,⽤户进程就进⼊到了内核态,通过执⾏⼀系列的内核协议层函数,然后到 socket 对象的接收队列中查看是否有数据,没有的话就把⾃⼰添加到 socket 对应的等待队列⾥…...

【iOS】内存五大分区
目录 堆(Heap)是什么五大分区栈区堆区全局/静态区常量区(即.rodata)代码区(.text) 函数栈堆和栈的区别和联系图解 OC语言是C语言的超集,所以先了解C语言的内存模型的内存管理会有很大帮助。C语言…...

Jupyter Notebook: 是一个强大的交互式计算
文章目录 引言Jupyter Notebook的原理基础使用安装与启动单元格(Cell)操作快捷键 高级使用魔术命令Markdown支持可视化版本控制 优缺点优点缺点 官网链接结论 引言 Jupyter Notebook是一个强大的交互式计算环境,特别适用于数据科学、机器学习…...

【C#学习笔记】变量、变量类型
在C#中,变量是存储数据的容器,每个变量都有其特定的数据类型,这决定了变量可以存储的数据类型和大小。以下是关于C#中变量的由浅入深的详细解释,并附带代码示例和解释: 基础概念 定义: 变量是存储数据的容…...

题解:T480718 eating
eating 题目背景 从前有个荣光的王国,小 A 是里面的国王,今天他要赐予他的子民以仓廪。 题目描述 在一条街上有 n n n 个饭店。小 A 站在这条街的最左端。 第 i i i 个饭店离这条街最左端的距离是 a i a_i ai,它所售卖的菜品的美味…...

MATLAB中matfile用法
目录 语法 说明 示例 创建 MAT 文件对象 启用对 MAT 文件的写访问权限 加载整个变量 将整个变量保存至现有 MAT 文件 加载和保存部分变量 确定变量大小 参数说明 局限性 提示 matfile的功能是访问和更改 MAT 文件中的变量,而不必将文件加载到内存中。 …...

Spring之Spring Bean的生命周期
Spring Bean的生命周期 通过BeanDefinition获取bean的定义信息调用构造函数实例化beanBean的依赖注入处理Aware接口(BeanNameAware、BeanFactoryAware、ApplicationContextAware)Bean的后置处理器BeanPostProcessor-前置初始化方法(Initiali…...

OSINT 开源情报中的地理定位方法
了解 OSINT 中的地理定位技术、如何获取地理位置数据以及如何将地理定位用于各种调查场景。 OSINT 中的地理定位基础知识 OSINT 代表开源情报,指的是从免费公共来源合法收集的有关个人或组织的信息。这包括在互联网上以及书籍、公共图书馆报告、报纸文章、新闻稿、…...

Java面试题系列 - 第17天
Java中的代理模式与动态代理 背景说明:代理模式是一种结构型设计模式,用于在客户端和目标对象之间提供一个代理或占位符。在Java中,动态代理技术允许在运行时创建代理对象,这在AOP(面向切面编程)和RPC&…...

开发环境搭建
1、Ubuntu 系统设置 root 用户密码 新安装的ubuntu没有设置 root 用户密码,打开终端,输入 sudo passwd root 执行命令后依次输入密码 2、虚拟机设置网络适配器 3、Ubuntu 系统下搭建 FTP 服务器 sudo apt-get update sudo apt-get install vsftpd sudo apt-get install vim…...

【NLP】关于参数do_sample的解释
在自然语言处理(NLP)领域,特别是在使用神经网络模型进行文本生成时,do_sample是一个常见的参数,用于控制模型生成文本的方式。具体来说,do_sample参数决定模型是否采用随机采样(sampling&#x…...

Vbox虚拟机+Ubuntu motest测试drm
1. 效果演示 大家做学习drm的时候,没有硬件测试平台不方便测试,这里给大家演示下如何基于Vbox虚拟机Ubuntu测试drm的一些功能,先看下演示视频。 没有光标测试: demo_vwmfgx_test_drm 带有光标测试: demo_vwmfgx_drm_with_cursor 可以看到,有…...

ArcGIS Pro SDK (九)几何 15 转换
ArcGIS Pro SDK (九)几何 15 转换 文章目录 ArcGIS Pro SDK (九)几何 15 转换1 创建地理转换2 创建复合地理变换3 创建投影转换4 创建高压基准变换5 创建复合高压基准变换6 决定转换7 地图点 - 地理坐标字符串转换 环境࿱…...

Spring IOC DI --- 认识IOC DI
T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 今天你敲代码了吗 文章目录 认识Ioc & DIIoc是什么?DI是什么? 认识Ioc & DI 我们知道,Spring 是一个开源框架,让我们的开发更加简单.但是更加具体来说,实际上Spring 是包含了众多工具方法的Ioc容器 …...

常用的python程序汇总——入门级
只用于记录最近的一些日常程序。 目录 前言 一、文件和目录管理 1.读取文件结构 读取所有文件夹和文件 读取到N级子文件夹和文件 只读取到N级子文件夹 2.遍历文件并处理(复制、删除) 说明: 二、数据分析和处理 三、数据可视化 四、…...

被问到MQ消息已丢失,该如何处理?
在分布式系统中,消息中间件(如 RabbitMQ、RocketMQ、Kafka、Pulsar 等)扮演着关键角色,用于解耦生产者和消费者,并确保数据传输的可靠性和顺序性。尽管我们通常会采取多种措施来防止消息丢失,如消息持久化、…...

open3d:ransac分割多个平面(源码)
1、背景介绍 随机采样一致性算法(RANSAC Random Sample Consensus)是一种迭代的参数估计算法,主要用于从包含大量噪声数据的样本中估计模型参数。其核心思想是通过随机采样和模型验证来找到数据中最符合模型假设的点。因此,只要事先给定要提取的参数模型,即可从点云中分割…...

Github 2024-07-17 开源项目日报 Top10
根据Github Trendings的统计,今日(2024-07-17统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量非开发语言项目3Python项目3Rust项目2TypeScript项目2MDX项目1项目化学习 创建周期:2538 天协议类型:MIT LicenseStar数量:161973 个Fork数量…...