C++友元:跨墙访问的三种姿势

目录

友元

友元之普通函数形式

友元之成员函数形式

友元类

友元的特点


友元

  • 什么叫友元?

一般来说,类的私有成员只能在类的内部访问,类之外是不能访问它们的。但如果将其他类/函数设置为类的友元,那么友元类/函数就可以在前一个类的类定义之外访问其私有成员了。用friend关键字声明友元

将类比作一个家庭,类的private 成员相当于家庭的秘密,一般的外人当然不允许探听这些秘密的,只有 friend 才有资格探听这些秘密。

友元的三种形式:普通函数、成员函数、友元类

友元之普通函数形式

示例:程序中有Point类,需要求取两个点的距离。按照设想,我们定义一个普通函数distance,接收两个Point对象作为参数,通过公式计算这两个点之间的距离。但Point的_ix和 _iy是私有成员,在类外不能通过对象访问,那么可以将distance函数声明为Point类的友元函数,之后就可以在distance函数中访问Point的私有成员了。

class Point{
public:Point(int x, int y): _ix(x), _iy(y){}
​friendfloat distance(const Point & lhs, const Point & rhs);
private:int _ix;int _iy;
};
​
float distance(const Point & lhs, const Point & rhs){return sqrt((lhs._ix - rhs._ix)*(lhs._ix - rhs._ix) +(lhs._iy - rhs._iy)*(lhs._iy - rhs._iy));
}

image-20240312161218053

友元之成员函数形式

假设类A有一个成员函数,该成员函数想去访问另一个类B类中的私有成员变量。这时候则可以在第二个类B中,声明第一个类A的那个成员函数为类B的友元函数,这样第一个类A的某个成员函数就可以访问第二个类B的私有成员变量了。

我们试验一下,以另一种方式实现上面的需求,如果distance函数不再是一个普通函数,而是Line类的一个成员函数,也就是说需要在一个类(Line)的成员函数中访问另一个类(Point)的私有成员,那么又该如何实现呢?

  • 如果将Point类定义在Line类之前,Line类的成员函数要访问Point类的私有成员,需要在Point类中将Line的这个成员函数设为友元函数——此时编译器并不认识Line类;

  • 如果将Line类定义在Point类之前,那么distance函数需要接受两个const Point &作为参数——此时编译器不认识Point类;

解决方法:

——在Line前面做一个Point类的前向声明;

——但如果将distance的函数体写在Line类中,编译器虽然知道了有一个Point类,但并不知道Point类具体有什么成员,所以此时在函数体中访问_ix、 _iy都会报错,编译器并不认识它们;

思考一下,有什么办法可以解决这个问题呢?

class Point;//前行声明
//只有前向声明,只知道有piont这个类,不知道point是怎么实现的,但不能访问point的内容,那么我们在line类中
//只做函数的声明,不做定义
class Line
{//需要前向声明,使编译器知道有piont这个类public:float destance(const Point &lhs,const Point &rhs);
};
class Point
{public:Point(int x,int y):_ix(x),_iy(y){}//friend friend float Line::destance(const Point &lhs,const Point &rhs);
​private:int _ix;int _iy;
};
​
//point 有什么东西编译器已经知道,现在对destance做定义就可以了,在外面是普通函数,就上作用域
float Line::destance(const Point &lhs,const Point &rhs)
{return sqrt(pow(lhs._ix - rhs._ix ,2)+pow(lhs._iy - rhs._iy,2));
}
 

image-20240312162223639

补充:

前向声明的用处:进行了前向声明的类,可以以引用或指针的形式作为函数的参数,只要不涉及到对该类对象具体成员的访问,编译器可以通过。

(让编译器认识这个类,但是注意如果只进行前向声明,这个类的具体实现没有的话,无法使用这个类的对象,无法创建)

注意:友元的声明要注意和函数的形式完全对应上。

友元类

如上的例子,假设类 Line 中不止有一个 distance 成员函数,还有其他成员函数,它们都需要访问Point 的私有成员,如果还像上面的方式一个一个设置友元,就比较繁琐了,可以直接将 Line 类设置为 Point 的友元类,在工作中这也是更常见的方法。

class Point {//...friend class Line;//...
};

在Point类中声明Line类是本类的友元类,那么Line类中的所有成员函数中都可以访问Point类的私有成员。一次声明,全部解决。

image-20240312163304583

不可否认,友元将类的私有成员暴露出来,在一定程度上破坏了信息隐藏机制,似乎是种“副作用很大的药”,但俗话说“良药苦口”。好工具总是要付出点代价的,拿把锋利的刀砍瓜切菜,总是要注意不要割到手指的。

友元的存在,使得类的接口扩展更为灵活,使用友元进行运算符重载从概念上也更容易理解一些,而且, C++ 规则已经极力地将友元的使用限制在了一定范围内。

友元的特点

  1. 友元不受类中访问权限的限制——可访问私有成员

  2. 友元破坏了类的封装性

  3. 不能滥用友元 ,友元的使用受到限制

  4. 友元是单向的——A类是B类的友元类,则A类成员函数中可以访问B类私有成员;但并不代表B类是A类的友元类,如果A类中没有声明B类为友元类,此时B类的成员函数中并不能访问A类私有成员

  5. 友元不具备传递性——A是B的友元类,B是C的友元类,无法推断出A是C的友元类

  6. 友元不能被继承——因为友元破坏了类的封装性,为了降低影响,设计层面上友元不能被继承

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39224.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typora安装使用教程 简单易用的Markdown编辑器

Typora markdown 编辑器下,最后一个免费版本 0.11.18,但可能会提示过期无法使用, 建议大家可以使用 0.9.96 Windows 版,下载 Windows X64 版。 Typora简介 Typora 是一款由 Abner Lee 开发的轻量级 Markdown 编辑器,与其他 Mark…

图解AUTOSAR_SWS_WatchdogInterface

AUTOSAR Watchdog Interface (WdgIf) 详解 AUTOSAR经典平台看门狗接口模块技术详解 目录 1. 概述 1.1 WdgIf模块的作用1.2 WdgIf在AUTOSAR中的位置2. 架构设计 2.1 WdgIf架构概览2.2 接口设计2.3 序列设计3. 配置详解 3.1 配置参数3.2 配置结构3.3 配置类型4. 总结 4.1 主要特点…

(Arxiv-2025)Magic 1-For-1:在一分钟内生成一分钟视频剪辑

Magic 1-For-1:在一分钟内生成一分钟视频剪辑 paper是PKU发布在Arxiv 2025的工作 paper title:Magic 1-For-1: Generating One Minute Video Clips within One Minute Code:地址 Abstract 在本技术报告中,我们提出了 Magic 1-For-1&#xff…

谷歌大型推理模型曝光!击败Claude-3.7-Thinking

哎!最近推特上的网友在LMSYS Arena 发现了个泄漏的大模型 Nebula,效果据说特别好,打败了o1、o3-mini、Claude 3.7 Thinking等模型: 网友们通过询问和分析 API,发现这似乎是谷歌正在秘密测试的新推理模型!推…

css-grid布局

文章目录 1、布局2、网格轨道3、间距Gap4、网格线5、网格别名 当一个 HTML 元素将 display 属性设置为 grid 或 inline-grid 后,它就变成了一个网格容器,这个元素的所有直系子元素将成为网格元素。 1、布局 启用grid布局类似与flex布局,不过g…

菱形虚拟继承的原理

一 :菱形继承的问题 普通的菱形继承存在数据冗余和二义性的问题 ,如下代码: class Person { public:string _name; //姓名 };class Student : public Person { protected:int _num; //学号 };class Teacher : public Person { protected:int…

<数据集>轨道异物识别数据集<目标检测>

数据集下载链接:https://download.csdn.net/download/qq_53332949/90527370 数据集格式:VOCYOLO格式 图片数量:1659张 标注数量(xml文件个数):1659 标注数量(txt文件个数):1659 标注类别数:6 标注类别…

高效PDF翻译解决方案:多引擎支持+格式零丢失

软件介绍 在AI翻译工具大行其道的今天,传统翻译软件市场逐渐饱和,但专业领域的深度需求依然存在。本文推荐的PDF翻译工具凭借20余种专业翻译接口,为学术文献、技术文档等复杂内容提供更精准的翻译服务,在保留文档原始排版的同时…

AI智能新标尺:诺姆·布朗谈token成本革命

第一章:从德州扑克到AI革命——诺姆布朗的“顿悟时刻” 1.1 从“人机对战”到“思维革命” 诺姆布朗的AI研究生涯始于2012年卡内基梅隆大学的实验室。彼时,国际象棋AI“深蓝”已横扫棋坛,围棋AI“AlphaGo”初露锋芒,但非完美信息…

碰一碰发视频系统开发者源码分析(一)

#碰一碰发视频系统# #碰一碰发视频saas系统#搭建 碰一碰发视频,是采用前沿技术搭载一套 AI 智能剪辑系统“碰一碰发视频”是一种基于近场通信(NFC)或蓝牙技术的创新交互方式,用户通过设备轻触即可触发视频传输或播放。本文将详细…

ROS2下MoveIt+Rviz+MuJoCo 三剑合璧!Panda 机械臂联动仿真!

视频讲解: ROS2下MoveItRvizMuJoCo 三剑合璧!Panda 机械臂联动仿真! 仓库代码:GitHub - LitchiCheng/ros2_package 今天介绍下,ros2下使用moveit在Rviz和mujoco联合仿真,结合上一期视频《MuJoCo 仿真 Pand…

Virtual BOX安装ubuntu及其环境配置(个人一些踩坑补充)

目录 设置中文操作界面和环境时候,下图内容切忌不要选错!安装过程中因为分辨率原因,可能安装界面无法显示全面,如何临时解决这篇文章中的缺少如何调出中文输出法部分unbuntu换源安装terminal终端小鱼一键ros安装opencv环境配置 ub…

基于Spring Boot的三国之家网站的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

二分图相关

判断二分图&#xff08;染色&#xff09; #include<bits/stdc.h> using namespace std; void __p(int x) {cerr<<x;} void __p(long long x){cerr<<x;} void __p(long double x){cerr<<x;} void __p(double x){cerr<<x;} void __p(string s){cer…

java执行jar包提示没有主清单属性

以前都没遇到过这种情况&#xff0c;什么时候打jar&#xff0c; war包都没有遇到过&#xff0c; 按照网上说的创建了META-INF/MANIFEST.MF 还是报错 于是检查下maven 打包发现&#xff1a;竟然有skip 为true 去掉 skip true &#xff0c;进行打包&#xff0c;编译后正常

运动仿真——phased.Platform

在雷达仿真过程中&#xff0c;运动仿真的必要性&#xff0c;以及运动仿真可以实现哪些功能&#xff0c;在matlab对应的user guide中已经讲的很清楚了&#xff0c;这里不再赘述。 本文主要介绍phased.Platform的一些“坑”&#xff0c;和典型的用法。 第一坑&#xff1a;系统对…

用selenium+ChromeDriver豆瓣电影 肖申克的救赎 短评爬取(pycharm 爬虫)

一、豆瓣电影 肖申克的救赎 短评url=https://movie.douban.com/subject/1292052/comments 二、基本知识点讲解 1. Selenium 的基本使用 Selenium 是一个用于自动化浏览器操作的库,常用于网页测试和爬虫。代码中使用了以下 Selenium 的核心功能: webdriver.Chrome: 启动 Chr…

万象更新(一)VTK 坐标轴、相机方向坐标轴、立方体坐标轴

VTK 坐标轴、相机方向坐标轴、立方体坐标轴 1. 坐标轴、相机方向坐标轴、立方体坐标轴2. 坐标轴3. 相机方向坐标轴4. 立方体坐标轴 1. 坐标轴、相机方向坐标轴、立方体坐标轴 在 VTK&#xff08;Visualization Toolkit&#xff09;中&#xff0c;与坐标轴相关的组件主要包括 坐…

【Golang】go语言上下文context

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

ROS2与OpenAI Gym集成指南:从安装到自定义环境与强化学习训练

1.理解 ROS2 和 OpenAI Gym 的基本概念 ROS2&#xff08;Robot Operating System 2&#xff09;&#xff1a;是一个用于机器人软件开发的框架。它提供了一系列的工具、库和通信机制&#xff0c;方便开发者构建复杂的机器人应用程序。例如&#xff0c;ROS2 可以处理机器人不同组…