CD27.【C++ Dev】类和对象 (18)友元和内部类
目录
1.友元
友元函数
几个特点
友元类
格式
代码示例
2.内部类(了解即可)
计算有内部类的类的大小
分析
注意:内部类不能直接定义
内部类是外部类的友元类
3.练习
承接CD21.【C++ Dev】类和对象(12) 流插入运算符的重载文章
1.友元
友元函数
在CD21.【C++ Dev】类和对象(12) 流插入运算符的重载文章中提到过,明确友元函数的特点:特点为:不受访问限定符限制,突破封装的限制,可访问类的私有和保护成员,这里介绍友元函数的几个特点
几个特点
1.友元函数是定义在类外部的普通函数,不是类的成员函数
2.友元函数不能用const修饰
解释:const修饰一般修饰的是成员函数,显然友元函数不属于任何类,无this指针,因此不能用const修饰

3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制
这个在CD21.【C++ Dev】类和对象(12) 流插入运算符的重载文章讲过了,不再赘述
4.一个函数可以是多个类的友元函数
因为友元函数不属于任何类,所以可以是多个类的友元函数
#include <iostream>
using namespace std;
class Myclass2;//前向声明
class Myclass1
{friend void function(const Myclass1& obj1, const Myclass2& obj2);
private:int _val = 1;
};class Myclass2
{friend void function(const Myclass1& obj1, const Myclass2& obj2);
private:int _val = 2;
};void function(const Myclass1& obj1, const Myclass2& obj2)
{cout << "function(),Myclass1's val=" <<obj1._val<< endl;cout << "function(),Myclass2's val=" <<obj2._val<< endl;
}
int main()
{Myclass1 obj1;Myclass2 obj2;function(obj1,obj2);return 0;
}
提醒:Myclass2必须前向声明,编译器默认是向上查找,否则编译器在遇到Myclass1的友元函数的声明friend void function(const Myclass1& obj1, const Myclass2& obj2);无法正确识别Myclass2
运行结果:

5.友元函数的调用与普通函数的调用原理相同
参见上方代码理解
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员,这是由friend的特性实现的
格式
friend class 类的名称
代码示例
#include <iostream>
using namespace std;
class Myclass1
{friend class Myclass2;//突破Myclass1的private限制
private:int _val = 1;};class Myclass2
{
public:void function(){cout << "Myclass1's _val:" << _obj._val << endl;}
private:Myclass1 _obj;//通过_obj去访问
};int main()
{Myclass2 obj;obj.function();return 0;
}
如果删除单词friend,那么就会报错:

运行结果:

2.内部类(了解即可)
顾名思义,即一个类声明在另一个类的里面,代码框架如下:
class Myclass1
{
public://......class innerclass{public://......private://......};
private://......
};
计算有内部类的类的大小
提问:obj对象的大小是多少?
#include <iostream>
using namespace std;
class Myclass
{
public:void function1(){cout << "void function1()" << endl;}class innerclass{public:int function2(){return 0;}private:static int _val2;};
private:int _val1;
};int main()
{Myclass obj;return 0;
}
分析
可以从运行结果来推测,使用以下代码:
int main()
{Myclass obj;cout << sizeof(obj) << endl;
}
运行结果:发现大小为4字节

从结果反推:
obj里面没有自定义类型为innerclass的对象,class Myclass里面写的class innerclass只是一个声明
且Myclass的成员没有innerclass的对象,因此只算了_val1的大小(注:不算function1函数的大小,函数存放在公共代码段,不存在对象中)
换句话说,类innerclass(不是对象)定义在Myclass的类域里面,但不占空间
注意:内部类不能直接定义
内部类不能直接定义会报错,需要通过外部类来间接定义内部类


如果只想定义内部类,可以这样写:
#include <iostream>
using namespace std;
class Myclass
{
public:class innerclass{public:static int _val2;};
};
int Myclass::innerclass::_val2 = 2;int main()
{Myclass::innerclass innerobj;cout << "innerobj._val2=" << innerobj._val2 << endl;return 0;
}
注意_val2定义的方式,不能将其定义在内部类和外部类之间,必须定义在类外(即外部类的外面) ,而且需要使用两次类名(Myclass::innerclass::)来定义
运行结果:

如果要加上类型为innerclass的对象大小,必须将innerclass实例化! 如下:
class Myclass
{
public://......
private:int _val1;innerclass _obj;//将类实例化
};
再次测试以下代码:
int main()
{Myclass obj;cout << sizeof(obj) << endl;
}
运行结果:

注意:这个大小并没有包含static int _val2的大小,因为_val2在静态区,而对象在栈区!
大小为8的计算方法:
Myclass的成员变量有两个:_val1和_obj,_va1占4字节,_obj占1字节(不允许出现空类,这一个字节纯属占位,之前在CD11.【C++ Dev】类和对象(2)文章提到过),4+1==5字节,但要按4字节对齐(最大对齐数的整数倍)以方便访问,因此再填充3个字节凑齐8个字节
有关类的内存对齐的知识点参见下面文章复习:
63.【C语言】再议结构体(上)
64.【C语言】再议结构体(下)
内部类是外部类的友元类
"友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员"
那么可以得出:内部类可以访问外部类的非公有成员,代码如下:
#include <iostream>
using namespace std;
class Myclass
{
public:void function1(){cout << "void function1()" << endl;}class innerclass{public:void function2(const Myclass& myobj){cout << "myobj._val1="<<myobj._val1 << endl;}private:static int _val2;};innerclass _obj;
private:int _val1=1;};int main()
{Myclass obj;obj._obj.function2(obj);
}
运行结果:

3.练习
之前在CD26.【C++ Dev】类和对象(17) static成员(下)文章解过JZ64 求1+2+3+...+n,可尝试使用内部类写,下篇将更新代码

相关文章:
CD27.【C++ Dev】类和对象 (18)友元和内部类
目录 1.友元 友元函数 几个特点 友元类 格式 代码示例 2.内部类(了解即可) 计算有内部类的类的大小 分析 注意:内部类不能直接定义 内部类是外部类的友元类 3.练习 承接CD21.【C Dev】类和对象(12) 流插入运算符的重载文章 1.友元 友元函数 在CD21.【C Dev】类和…...
QT安装详细步骤
下载 清华源 : 清华源 1. 2. 3. 4....
Unity游戏多语言工具包
由于一开始的代码没有考虑多语言场景,导致代码中提示框和UI显示直接用了中文,最近开始提取代码的中文,提取起来太麻烦,所以拓展了之前的多语言包,降低了操作复杂度。最后把工具代码提取出来到单独项目里面,…...
实验三 I/O地址译码
一、实验目的 掌握I/O地址译码电路的工作原理。 二、实验电路 实验电路如图1所示,其中74LS74为D触发器,可直接使用实验台上数字电路实验区的D触发器,74LS138为地址译码器, Y0:280H~287H&…...
视觉语言导航(VLN):连接语言、视觉与行动的桥梁
文章目录 1. 引言:什么是VLN及其重要性?2. VLN问题定义3. 核心挑战4. 基石:关键数据集与模拟器5. 评估指标6. 主要方法与技术演进6.1 前CLIP时代:奠定基础6.2 后CLIP时代:视觉与语言的统一 7. 最新进展与前沿趋势 (202…...
计算机网络中科大 - 第7章 网络安全(详细解析)-以及案例
目录 🛡️ 第8章:网络安全(Network Security)优化整合笔记📌 本章学习目标 一、网络安全概念二、加密技术(Encryption)1. 对称加密(Symmetric Key)2. 公钥加密࿰…...
2026《数据结构》考研复习笔记一(C++基础知识)
C基础知识复习 一、数据类型二、修饰符和运算符三、Lambda函数和表达式四、数学函数五、字符串六、结构体 一、数据类型 1.1基本类型 基本类型 描述 字节(位数) 范围 char 字符类型,存储ASCLL字符 1(8位) -128…...
XCTF-web(四)
unserialize3 需要反序列化一下:O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;} php_rce 题目提示rce漏洞,测试一下:?s/Index/\think\app/invokefunction&functioncall_user_func_array&vars[0]phpinfo&vars[1][]1 flag࿱…...
在Vue项目中查询所有版本号为 1.1.9 的依赖包名 的具体方法,支持 npm/yarn/pnpm 等主流工具
以下是 在Vue项目中查询所有版本号为 1.1.9 的依赖包名 的具体方法,支持 npm/yarn/pnpm 等主流工具: 一、使用 npm 1. 直接过滤依赖树 npm ls --depth0 | grep "1.1.9"说明: npm ls --depth0:仅显示直接依赖…...
若依微服务版启动小程序后端
目录标题 本地启动,dev对应 nacos里的 xxx-xxx-dev配置文件 本地启动,dev对应 nacos里的 xxx-xxx-dev配置文件...
莒县第六实验小学:举行“阅读世界 丰盈自我”淘书会
4月16日,莒县第六实验小学校园内书香四溢、笑语盈盈,以“阅读世界 丰盈自我”为主题的第二十四届读书节之“淘书会”活动火热开启。全校师生齐聚一堂,以书会友、共享阅读之乐,为春日校园增添了一抹浓厚的文化气息。 活动在悠扬的诵…...
国产数据库与Oracle数据库事务差异分析
数据库中的ACID是事务的基本特性,而在Oracle等数据库迁移到国产数据库国产中,可能因为不同数据库事务处理机制的不同,在迁移后的业务逻辑处理上存在差异。本文简要介绍了事务的ACID属性、事务的隔离级别、回滚机制和超时机制,并总…...
C++学习记录:
今天我们来学习一门新的语言,也是C语言最著名的一个分支语言:C。 在C的学习中,我们主要学习的三大组成部分:语法、STL、数据结构。 C的介绍 C的历史可追溯至1979年,当时贝尔实验室的本贾尼斯特劳斯特卢普博士在面对复杂…...
等离子体浸没离子注入(PIII)
一、PIII 是什么?基本原理和工艺 想象一下,你有一块金属或者硅片(就是做芯片的那种材料),你想给它的表面“升级”,让它变得更硬、更耐磨,或者有其他特殊功能。怎么做呢?PIII 就像是用…...
LeetCode-16.最接近的三数之和 C++实现
一 题目描述 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解 示例 1: 输入:nums [-1,2,1,-4], target 1 输出&…...
【机器学习】每日一讲-朴素贝叶斯公式
文章目录 **一、朴素贝叶斯公式详解****1. 贝叶斯定理基础****2. 从贝叶斯定理到分类任务****3. 特征独立性假设****4. 条件概率的估计** **二、在AI领域的作用****1. 文本分类与自然语言处理(NLP)****2. 推荐系统****3. 医疗与生物信息学****4. 实时监控…...
C 语言中的 volatile 关键字
1、概念 volatile 是 C/C 语言中的一个类型修饰符,用于告知编译器:该变量的值可能会在程序控制流之外被意外修改(如硬件寄存器、多线程共享变量或信号处理函数等),因此编译器不应对其进行激进的优化(如缓存…...
Python自学第1天:变量,打印,类型转化
突然想学Python了。经过Deepseek的推荐,下载了一个Python3.12安装。安装过程请自行搜索。 乖乖从最基础的学起来,废话不说了,上链接,呃,打错了,上知识点。 变量的定义 # 定义一个整数类型的变量 age 10#…...
探索鸿蒙应用开发:ArkTS应用执行入口揭秘
# 探索鸿蒙应用开发:ArkTS应用执行入口揭秘 在鸿蒙应用开发的领域中,ArkTS作为声明式开发语言,为开发者们带来了便捷与高效。对于刚接触鸿蒙开发的小伙伴来说,搞清楚ArkTS应用程序的执行入口是迈向成功开发的关键一步。今天&…...
idea中提高编译速度研究
探索过程: 有三种情况: 第一种: idea中用eclipse编译器编译springboot项目,然后debug启动Application报错找不到类。 有待继续研究。 第二种: idea中用javac编译器编译springboot项目,重新构建用时&a…...
静态链接part2
编译 语义分析 由语义分析器完成,这个步骤只是完成了对表达式的语法层面的分析,它并不了解这个语句是否真的有意义(例如在C语言中两个指针做乘法运算,这个语句在语法上是合法的,但是没有什么意义;还有同样…...
Vue3+Vite+TypeScript+Element Plus开发-17.Tags-组件构建
系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由 -动态增加路由 动态路由-动态删除…...
MATLAB R2023b如何切换到UTF-8编码,解决乱码问题
网上都是抄来抄去,很少有动脑子的,里面说的方法都差不多,但是在R2023b上怎么试都不管用,所以静下心来分析了下,我的 ...\MATLAB\R2016b\bin\lcdata.xml 里面除了注释几乎是空的,如果这样就能用为什么要加…...
3D语义地图中的全局路径规划!iPPD:基于3D语义地图的指令引导路径规划视觉语言导航
作者: Zehao Wang, Mingxiao Li, Minye Wu, Marie-Francine Moens, Tinne Tuytelaars 单位:鲁汶大学电气工程系,鲁汶大学计算机科学系 论文标题: Instruction-guided path planning with 3D semantic maps for vision-language …...
ShellScript脚本编程
语法基础 脚本结构 我们先从这个小demo程序来窥探一下我们shell脚本的程序结构 #!/bin/bash# 注释信息echo_str"hello world"test(){echo $echo_str }test echo_str 首先我们可以通过文本编辑器(在这里我们使用linux自带文本编辑神器vim),新建一个文件…...
【HarmonyOS 5】敏感信息本地存储详解
【HarmonyOS 5】敏感信息本地存储详解 前言 鸿蒙其实自身已经通过多层次的安全机制,确保用户敏感信息本地存储安全。不过再此基础上,用户敏感信息一般三方应用还需要再进行加密存储。 本文章会从鸿蒙自身的安全机制进行展开,最后再说明本地…...
大厂面试:六大排序
前言 本篇博客集中了冒泡,选择,二分插入,快排,归并,堆排,六大排序算法 如果觉得对你有帮助,可以点点关注,点点赞,谢谢你! 1.冒泡排序 //冒泡排序ÿ…...
.exe变成Windows服务
.exe变成Windows服务) 场景步骤 1: 安装 PyInstaller和win32serviceutil步骤 2: 使用 PyInstaller 创建 .exe 文件步骤 3: 检查生成的 .exe 文件步骤 4: 安装服务步骤 5: 启动服务步骤 6: 配置服务自动启动(可选)步骤 7: 检查服务状态完整示例…...
探索鸿蒙沉浸式:打造无界交互体验
一、鸿蒙沉浸式简介 在鸿蒙系统中,沉浸式是一种极具特色的设计理念,它致力于让用户在使用应用时能够全身心投入到内容本身,而尽可能减少被系统界面元素的干扰。通常来说,就是将应用的内容区巧妙地延伸到状态栏和导航栏所在的界面…...
el-tree组件使用过滤时,不展示筛选目标的子节点
1.el官方示例过滤方法 const filterNode (value: string, data: Tree) > {if (!value) return truereturn data.label.includes(value) }2.修改后的过滤方法 /*** 树节点过滤*/ const filterNode (value, data, node) > {if (!value) return true;let parentNode no…...
