CD27.【C++ Dev】类和对象 (18)友元和内部类

news2025/4/18 18:55:10

目录

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,可尝试使用内部类写,下篇将更新代码

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT安装详细步骤

下载 清华源 &#xff1a; 清华源 1. 2. 3. 4.

Unity游戏多语言工具包

由于一开始的代码没有考虑多语言场景&#xff0c;导致代码中提示框和UI显示直接用了中文&#xff0c;最近开始提取代码的中文&#xff0c;提取起来太麻烦&#xff0c;所以拓展了之前的多语言包&#xff0c;降低了操作复杂度。最后把工具代码提取出来到单独项目里面&#xff0c;…

实验三 I/O地址译码

一、实验目的 掌握I/O地址译码电路的工作原理。 二、实验电路 实验电路如图1所示&#xff0c;其中74LS74为D触发器&#xff0c;可直接使用实验台上数字电路实验区的D触发器&#xff0c;74LS138为地址译码器&#xff0c; Y0&#xff1a;280H&#xff5e;287H&…

视觉语言导航(VLN):连接语言、视觉与行动的桥梁

文章目录 1. 引言&#xff1a;什么是VLN及其重要性&#xff1f;2. VLN问题定义3. 核心挑战4. 基石&#xff1a;关键数据集与模拟器5. 评估指标6. 主要方法与技术演进6.1 前CLIP时代&#xff1a;奠定基础6.2 后CLIP时代&#xff1a;视觉与语言的统一 7. 最新进展与前沿趋势 (202…

计算机网络中科大 - 第7章 网络安全(详细解析)-以及案例

目录 &#x1f6e1;️ 第8章&#xff1a;网络安全&#xff08;Network Security&#xff09;优化整合笔记&#x1f4cc; 本章学习目标 一、网络安全概念二、加密技术&#xff08;Encryption&#xff09;1. 对称加密&#xff08;Symmetric Key&#xff09;2. 公钥加密&#xff0…

XCTF-web(四)

unserialize3 需要反序列化一下&#xff1a;O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;} php_rce 题目提示rce漏洞&#xff0c;测试一下&#xff1a;?s/Index/\think\app/invokefunction&functioncall_user_func_array&vars[0]phpinfo&vars[1][]1 flag&#xff1…

在Vue项目中查询所有版本号为 1.1.9 的依赖包名 的具体方法,支持 npm/yarn/pnpm 等主流工具

以下是 在Vue项目中查询所有版本号为 1.1.9 的依赖包名 的具体方法&#xff0c;支持 npm/yarn/pnpm 等主流工具&#xff1a; 一、使用 npm 1. 直接过滤依赖树 npm ls --depth0 | grep "1.1.9"说明&#xff1a; npm ls --depth0&#xff1a;仅显示直接依赖&#xf…

若依微服务版启动小程序后端

目录标题 本地启动&#xff0c;dev对应 nacos里的 xxx-xxx-dev配置文件 本地启动&#xff0c;dev对应 nacos里的 xxx-xxx-dev配置文件

莒县第六实验小学:举行“阅读世界 丰盈自我”淘书会

4月16日&#xff0c;莒县第六实验小学校园内书香四溢、笑语盈盈&#xff0c;以“阅读世界 丰盈自我”为主题的第二十四届读书节之“淘书会”活动火热开启。全校师生齐聚一堂&#xff0c;以书会友、共享阅读之乐&#xff0c;为春日校园增添了一抹浓厚的文化气息。 活动在悠扬的诵…

国产数据库与Oracle数据库事务差异分析

数据库中的ACID是事务的基本特性&#xff0c;而在Oracle等数据库迁移到国产数据库国产中&#xff0c;可能因为不同数据库事务处理机制的不同&#xff0c;在迁移后的业务逻辑处理上存在差异。本文简要介绍了事务的ACID属性、事务的隔离级别、回滚机制和超时机制&#xff0c;并总…

C++学习记录:

今天我们来学习一门新的语言&#xff0c;也是C语言最著名的一个分支语言&#xff1a;C。 在C的学习中&#xff0c;我们主要学习的三大组成部分&#xff1a;语法、STL、数据结构。 C的介绍 C的历史可追溯至1979年&#xff0c;当时贝尔实验室的本贾尼斯特劳斯特卢普博士在面对复杂…

等离子体浸没离子注入(PIII)

一、PIII 是什么&#xff1f;基本原理和工艺 想象一下&#xff0c;你有一块金属或者硅片&#xff08;就是做芯片的那种材料&#xff09;&#xff0c;你想给它的表面“升级”&#xff0c;让它变得更硬、更耐磨&#xff0c;或者有其他特殊功能。怎么做呢&#xff1f;PIII 就像是用…

idea中提高编译速度研究

探索过程&#xff1a; 有三种情况&#xff1a; 第一种&#xff1a; idea中用eclipse编译器编译springboot项目&#xff0c;然后debug启动Application报错找不到类。 有待继续研究。 第二种&#xff1a; idea中用javac编译器编译springboot项目&#xff0c;重新构建用时&a…

静态链接part2

编译 语义分析 由语义分析器完成&#xff0c;这个步骤只是完成了对表达式的语法层面的分析&#xff0c;它并不了解这个语句是否真的有意义&#xff08;例如在C语言中两个指针做乘法运算&#xff0c;这个语句在语法上是合法的&#xff0c;但是没有什么意义&#xff1b;还有同样…

Vue3+Vite+TypeScript+Element Plus开发-17.Tags-组件构建

系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由 -动态增加路由 动态路由-动态删除…

3D语义地图中的全局路径规划!iPPD:基于3D语义地图的指令引导路径规划视觉语言导航

作者&#xff1a; Zehao Wang, Mingxiao Li, Minye Wu, Marie-Francine Moens, Tinne Tuytelaars 单位&#xff1a;鲁汶大学电气工程系&#xff0c;鲁汶大学计算机科学系 论文标题&#xff1a; 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)&#xff0c;新建一个文件…

【HarmonyOS 5】敏感信息本地存储详解

【HarmonyOS 5】敏感信息本地存储详解 前言 鸿蒙其实自身已经通过多层次的安全机制&#xff0c;确保用户敏感信息本地存储安全。不过再此基础上&#xff0c;用户敏感信息一般三方应用还需要再进行加密存储。 本文章会从鸿蒙自身的安全机制进行展开&#xff0c;最后再说明本地…

探索鸿蒙沉浸式:打造无界交互体验

一、鸿蒙沉浸式简介 在鸿蒙系统中&#xff0c;沉浸式是一种极具特色的设计理念&#xff0c;它致力于让用户在使用应用时能够全身心投入到内容本身&#xff0c;而尽可能减少被系统界面元素的干扰。通常来说&#xff0c;就是将应用的内容区巧妙地延伸到状态栏和导航栏所在的界面…

网站301搬家后谷歌一直不收录新页面怎么办?

当网站因更换域名或架构调整启用301重定向后&#xff0c;许多站长发现谷歌迟迟不收录新页面&#xff0c;甚至流量大幅下滑。 例如&#xff0c;301跳转设置错误可能导致权重传递失效&#xff0c;而新站内容与原站高度重复则可能被谷歌判定为“低价值页面”。 即使技术层面无误&a…