当前位置: 首页 > news >正文

《C++初阶之类和对象》【友元 + 内部类 + 匿名对象】

什么是友元?

友元(Friend):是一种允许非成员函数其他类访问某个类的私有(private)和保护(protected)成员的机制。

  • 通过友元,类可以有选择地向特定的外部实体开放其封装的细节,增强灵活性的同时保持封装性的控制。
友元有哪三种形式?

友元的三种的形式分别是:

  1. 友元函数
  2. 友元类
  3. 友元成员函数

友元函数(Friend Function):允许外部函数访问类的私有 / 保护成员。语法:在类中使用friend关键字声明函数。示例

代码语言:javascript

AI代码解释

class Rectangle { private: int width, height; public: friend int getArea(const Rectangle& rect); // 友元函数声明 }; int getArea(const Rectangle& rect) { return rect.width * rect.height; // 可访问私有成员 }

友元类(Friend Class):允许整个类访问另一个类的私有 / 保护成员。语法:在类中使用friend class声明友元类。示例

代码语言:javascript

AI代码解释

class A { private: int data; friend class B; // 类B是类A的友元 }; class B { public: void accessA(A& a) { a.data = 42; // 类B可访问类A的私有成员 } };

友元成员函数(Friend Member Function):允许某个类的特定成员函数访问另一个类的私有 / 保护成员。语法:在类中声明另一个类的特定成员函数为友元。示例

代码语言:javascript

AI代码解释

class A; // 前向声明 class B { public: void func(A& a); // 成员函数声明 }; class A { private: int data; friend void B::func(A& a); // 声明B的成员函数为友元 }; void B::func(A& a) { a.data = 42; // 可访问类A的私有成员 }
怎么使用友元函数?

代码语言:javascript

AI代码解释

#include<iostream> using namespace std; // 前置声明 // 因为func函数中需要用到B类,而B类的定义在后面 // 所以需要提前告诉编译器B是一个类 class B; /*------------------------------类A的定义------------------------------*/ class A { /*----------------------友元函数声明----------------------*/ // 友元函数声明:func可以访问A的私有成员 friend void func(const A& aa, const B& bb); // 注意:虽然func函数参数中用到了B类,但这里只需要B的前置声明 private: int _b1 = 3; int _b2 = 4; }; /*------------------------------类B的定义------------------------------*/ class B { // 注意:func不是B的友元,所以不能访问B的私有成员 // 为了让func能访问_b1,我们需要将其设为public public: int _b1 = 5; private: int _b2 = 6; }; /*----------------------友元函数的定义----------------------*/ /** * @brief 友元函数定义 * @param aa A类对象的常量引用 * @param bb B类对象的常量引用 * * 此函数可以访问A的私有成员,但不能访问B的私有成员 */ void func(const A& aa, const B& bb) { cout << aa._b1 << endl; // 可以访问A的私有成员_b1(输出3) cout << aa._b2 << endl; // 也可以访问_b2 cout << bb._b1 << endl; // 只能访问B的公有成员_b1(输出5) //cout << bb._b2 << endl; // 错误!不能访问B的私有成员_b2 } int main() { A aa; // 创建A类对象 B bb; // 创建B类对象 func(aa, bb); // 调用友元函数 return 0; } /* * 关键点总结: * 1. 友元函数声明: * - 在A类内部用friend声明func为友元函数 * - func可以访问A的所有成员(包括私有成员) * * 2. 前置声明: * - 因为func的参数中用到了B类,而B类的定义在后面 * - 所以需要在文件开头使用class B;进行前置声明 * * 3. 访问权限: * - func可以访问A的私有成员_b1和_b2 * - func不能访问B的私有成员(除非B也声明func为友元) * * 4. 注意事项: * - 友元函数不是类的成员函数,只是被特别授权访问私有成员 */

在这里插入图片描述

怎么使用友元类?

代码语言:javascript

AI代码解释

#include<iostream> using namespace std; /*------------------------------类B的定义------------------------------*/ //该类将B类声明为友元,允许B访问其私有成员 class A { // 友元类声明:B是A的友元类 // 这意味着B的所有成员函数都可以访问A的私有成员 friend class B; private: int _a1 = 1; int _a2 = 2; }; /*------------------------------类B的定义------------------------------*/ //A的友元类,可以访问A的私有成员 class B { public: /*----------------------友元函数的定义----------------------*/ /** * @brief 访问A的私有成员_a1和B的私有成员_b1 * @param aa A类对象的常量引用 */ void func1(const A& aa) { cout << aa._a1 << endl; cout << _b1 << endl; } /*----------------------友元函数的定义----------------------*/ /** * @brief 访问A的私有成员_a2和B的私有成员_b2 * @param aa A类对象的常量引用 */ void func2(const A& aa) { cout << aa._a2 << endl; cout << _b2 << endl; } private: int _b1 = 3; int _b2 = 4; }; int main() { A aa; // 创建A类对象 B bb; // 创建B类对象 // 调用B的成员函数,演示友元访问 bb.func1(aa); // 输出:1 和 3 bb.func2(aa); // 输出:2 和 4 return 0; } /* * 关键点总结: * 1. 友元类声明: * - 在A类内部使用 friend class B; 声明 * - 这使得B类的所有成员函数都可以访问A的私有成员 * * 2. 访问权限: * - B类可以访问A的私有成员_a1和_a2 * - 但A类不能访问B的私有成员(友元关系是单向的) */

在这里插入图片描述

关于友元我们有哪些需要注意的事情?

1. 访问权限相关

  • 突破封装:友元函数或友元类能访问对应类的privateprotected成员,打破了类的常规封装机制,让特定外部代码可操作类的内部数据,增强了灵活性,但也一定程度破坏了封装性,使用时需谨慎。
  • 访问权限不受限:在类中声明友元时,不管放在publicprivate还是protected部分,效果都一样,都能获得相应的访问权限。
http://www.jsqmd.com/news/474826/

相关文章:

  • 当变频器遇上S7-200:一个水厂老司机的自白
  • 基于CW32F030C8T6的BMP180气压传感器I2C驱动移植与海拔测量实战
  • 《C++初阶之STL》【auto关键字 + 范围for循环 + 迭代器】
  • 2026年混凝土外加剂实力厂家甄选指南与TOP5推荐 - 2026年企业推荐榜
  • 八皇后(dfs 模版
  • YOLOv5+GraspNet实战:如何用Python快速搭建机械臂抓取系统(附完整代码)
  • ESP32S3基础2-多任务处理、EXTI中断、时钟与定时器
  • MySQL【表的约束下】
  • 手把手教你用阿里云镜像制作glibc.i686离线安装包(CentOS7专属)
  • [特殊字符] Nano-Banana实战案例:从手机到家电,全品类产品拆解图生成实录
  • Zotero7文献笔记模版:从安装到自定义的完整指南
  • 喜讯!第十六批生成合成类算法备案备案号公布
  • 天梯赛编程题 L2—048 寻宝图 题解
  • 软件安全实战指南:从零日漏洞到安全部署的核心要义
  • Visual Studio误删.vcxproj.filters文件?3步教你手动重建(附模板)
  • Unity URP渲染管线进阶---自定义RendererFeature实战解析
  • 阿姆智创21.5寸嵌入式工控一体机,多场景智造的嵌入式终端,源头工厂ODM定制应用
  • 衡山派D133EBS开发板驱动MS1100 VOC气体传感器实战指南
  • Linux用户必备:5款免费CAD软件实测对比(附安装指南)
  • OpenMV实战指南:sensor与image模块的高效配置与图像处理技巧
  • 从SCAU综合实验到实战:C语言文件操作与字符处理的进阶解析
  • 避坑指南:PyQt5+Matplotlib动态绘图卡顿?试试这3种优化方案
  • PyTorch量化实战:从模型压缩到移动端部署
  • ENVI遥感图像处理入门实战:从数据加载到基础分析
  • 告别WebSecurityConfigurerAdapter:Spring Security 5.7+组件化配置实战
  • LangGraph实战进阶(二)——巧用条件边与循环构建可自愈的智能体
  • LegionFanControl报错?手把手教你解决TextWriter关闭问题(附Defender白名单设置)
  • 思博伦Spirent TestCenter中高效配置单播流uni-stream的实战指南
  • Ascend平台下的PageAttention优化实践
  • 从颜真卿到赵孟頫:用zi2zi-chain复刻历代书法名家字体的完整流程