【C++】类与对象——友元,内部类,匿名对象

news2024/10/2 22:23:45

在这里插入图片描述

类与对象

  • 1 友元
    • 1.1 概念:
    • 1.2 友元函数
    • 1.3 友元类
  • 2 内部类
    • 概念:
    • 特性:
    • 举例:
  • 3 匿名对象
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 友元

1.1 概念:

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不易多用
友元分为:友元函数 和 友元类
友元关键字 :friend 可以理解为我把他看做朋友,所以他可以使用我的东西。这就是友元做到的事情是类似的,通过设置友元,在一个类中可以访问类外的函数与变量。

1.2 友元函数

我们现在来实现日期类Date的流输出<<重载,那么我们来看:

class Date
{
public:
   Date(int year, int month, int day)
   {
   	_year = year;
   	_month = month;
   	_day = day;
   	
   }
   //这里 参数有两个 (Date* this , ostream& out )
   //左右操作数不一致。
   ostream& operator<<(ostream& out) {
   	out << _year << '-' << _month << '-' << _day << endl;
   	return out;
   }
private:
   int _year;
   int _month;
   int _day;
};

int main(){
   Date a1(2024,2,24);
   cout << a1;
   return 0;
}

这样必然会出现问题,因为在成员函数中第一个参数默认为(Date* this)所以在使用<<时就会出现参数不匹配环节。
在这里插入图片描述

所以要想改变默认参数的顺序,就要把operator<<重载为全局函数,但是这样无法访问Date的私有变量,此时就可以通过友元来解决这个问题。来看修改后的代码

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;

	}
	friend ostream& operator<<(ostream& out, Date& d);
private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& out, Date&  d) {
	out << d._year << '-' << d._month << '-' << d._day << endl;
	return out;
}

int main() {
	Date a1(2024, 2, 24);
	cout << a1;
	return 0;
}

现在就可以顺利的使用<<重载了。在这里插入图片描述

总结一下:
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在
类的内部声明,声明时需要加friend关键字。

友元声明只能出现在类定义的内部,但是类内出现的具体位置不限。友元不是类的成员也不受它所在区域访问控制级别的约束。一般来说,最好在类定义开始或结束区域集中声明友元。

注意:

  1. 友元函数可访问类的私有和保护成员,但不是类的成员函数
  2. 友元函数不能用const修饰
  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  4. 一个函数可以是多个类的友元函数
  5. 友元函数的调用与普通函数的调用原理相同

1.3 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类的非公用成员。

  1. 友元关系是单向的,不具有交换性(注意A类中声明友元B类,那么B类可以访问A类,但是A类不能访问B类),类似小明说小刚是他的朋友,但是小刚不一定把小明当做朋友。
  2. 友元关系不能传递(如果C类是B类的友元,B类是A类的友元,不能说明C类是A类的友元)
  3. 友元关系不能继承。

下面给出时间类Time 与 日期类Date 的示例,来帮助我们更好理解友元。
在这里插入图片描述
Time类中声明友元即可成功:

class Time
{
	// 声明日期类为时间类的友元类,
	//则在日期类中就直接访问Time类中的私有成员变量
	friend class Date;
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};

2 内部类

概念:

如果一个类定义在另一个类的内部,这个内部类就叫做内部类
内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员外部类对内部类没有任何优越的访问权限

特性:

注意: 内部类就是外部类友元类,内部类可以通过外部类的对象参数来访问外部类的所有成员,但是外部类不是内部类的友元。

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
  3. sizeof(外部类)=外部类,和内部类没有任何关系

举例:

可以把友元实现的打印日期形成内部类,也可以做到相同效果。

#include<cstdio>
#include<iostream>
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
	定义内部类
	class Time
	{
		friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类
	中的私有成员变量
	public:
		Time(int hour = 0, int minute = 0, int second = 0)
			: _hour(hour)
			, _minute(minute)
			, _second(second)
		{}
		void show(Date& d){
			printf("时间是 %d年%d月%d日%d时%d分%d秒", d._year, d._month, d._day, 					
			_hour,_minute,_second);
		}
	private:
		int _hour;
		int _minute;
		int _second;
};
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main() {
	Date d1(2024, 2, 26);
	Date::Time t1(11, 26, 30);
	t1.show(d1);
}

来看效果:非常好!!!
在这里插入图片描述

3 匿名对象

匿名对象可以帮助我们优化语句:

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
    ~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
class Solution {
public:
	int Sum_Solution(int n) {
		//...
		return n;
	}
};
int main()
{
	A aa1;
	// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义
	//A aa1();
	// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,
	// 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数
	A();
	A aa2(2);
	// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说
	Solution().Sum_Solution(10);
	return 0;
}

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

基于Java的艺培管理解决方案

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

Canvas动画之豌豆射手

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

多线程基础说明【基础篇】

目录 &#x1f32d;1.相关概念 &#x1f37f;2.创建和启动线程 &#x1f95e;3.线程安全 &#x1f9c8;4.死锁 &#x1f953;5.线程通信的方法 1.相关概念 1.1程序 为完成特定任务&#xff0c;用某种语言编写的一组指令的集合。即指一段静态的代码&#xff0c;静态对象…

Flask基础学习3

参考视频&#xff1a;41-【实战】答案列表的渲染_哔哩哔哩_bilibili flask 实现发送短信功能 pip install flask-mail # 安装依赖 我这里用登录的网易邮箱获取的授权码&#xff08;登录QQ邮箱的授权码总是断开收不到邮件&#xff09;&#xff0c; # config # config mail MAI…

vue3 实现 el-pagination页面分页组件的封装以及调用

示例图 一、组件代码 <template><el-config-provider :locale"zhCn"><el-pagination background class"lj-paging" layout"prev, pager, next, jumper" :pager-count"5" :total"total":current-page"p…

LeetCode二叉树中的第 K 大层和

题目描述 给你一棵二叉树的根节点 root 和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返回 -1 。 注意&#xff0c;如果两个节点与根节点的距离相同&#xff0c;则…

SocketWeb实现小小聊天室

SocketWeb实现小小聊天室 消息推送的常见方式轮询长轮询SSE&#xff08;server-sent event&#xff09;&#xff1a;服务器发送事件WebSocketWebSocket简介WebSocket API 实现小小聊天室实现流程消息格式客户端-->服务端服务端-->客户端 消息推送的常见方式 轮询 浏览器…

C# TesseractOCR识别身份证号

https://github.com/tesseract-ocr/tessdata 新建控制台项目并添加包 Tesseract和Tesseract.Drawing 下载训练的模型 地址 代码实现 using Tesseract;var filePath "F:\\Desktop\\韦小宝.png"; var exePath AppDomain.CurrentDomain.BaseDirectory; var …

远程连接Redis

以连接阿里云上的Redis为例 1. 在阿里云安全组中开放端口 2.修改Redis启动时所用的配置文件&#xff08;redis.conf&#xff09; 2.1 修改ip地址 如图&#xff1a;将默认的本地ip bind 127.0.0.1地址改为bind 0.0.0.0 2.2 将保护模式关闭 将默认的 supervised yes 改为 n…

Docker基础(一)

文章目录 1. 基础概念2. 安装docker3. docker常用命令3.1 帮助命令3.2 镜像命令3.3 容器命令3.4 其他命令 4. 使用案例 1. 基础概念 镜像&#xff08;Image&#xff09;&#xff1a;Docker 镜像&#xff08;Image&#xff09;&#xff0c;就相当于是一个 root 文件系统。比如官…

Java Web(八)--Servlet(一)

介绍 官网&#xff1a;Servlet 3.1 API Documentation - Apache Tomcat 8.0.53 为什么需要&#xff1f; 提出需求: 请用你现有的html css javascript&#xff0c;开发网站&#xff0c;比如可以让用户留言/购物/支付? 引入我们动态网页(能和用户交互)技术>Servlet 是什…

医院LIS(全称Laboratory Information Management System)系统源码

目录 一、医院LIS系统概况 二、医院LIS系统建设必要性 三、为什么要使用LIS系统 四、技术框架 &#xff08;1&#xff09;总体框架 &#xff08;2&#xff09;技术细节 &#xff08;3&#xff09;LIS主要功能模块 五、LIS系统优势 &#xff08;1&#xff09;客户/用户…

【Python】记录生产编程小tips(字符串处理、列表删除、字典、csv、excel操作)持续更新

文章目录 一.for循环删除列表元素1.删除list元素方法2.直接删除往往结果与期望不一致3.循环删除元素的正确方法&#xff1a;方法1&#xff1a;while循环i减方法2&#xff1a;使用copy方法3&#xff1a;倒叙遍历 二.字符串处理库三.字典—dict运用四.csv操作五.excel操作1.读exc…

AI:139-基于深度学习的语音指令识别与执行

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

改进 RAG:自查询检索

原文地址&#xff1a;Improving RAG: Self Querying Retrieval 2024 年 2 月 11 日 让我们来解决构建 RAG 系统时的一个大问题。 我们不能依赖语义搜索来完成每个检索任务。只有当我们追求单词的含义和意图时&#xff0c;语义搜索才有意义。 But in case&#xff0c;我们正…

python自动化管理和zabbix监控网络设备(有线网络和路由配置部分)

目录 目录 一、拓扑图 二、core-sw1 三、core-sw2 四、sum-sw1 五、sum-sw2 六、FW1 七、DMZ-SW1 结语 一、拓扑图 二、core-sw1 sys sysname core-sw1 vlan batch 10 20 30 40 50 60 100 vlan batch 200 210 220 230 240 250 stp region-configuration region-name…

选择稳定代理IP需要考虑哪些因素?

很多人不知道怎么选择稳定的代理IP&#xff0c;也不知道当前代理IP套餐是否稳定&#xff0c;今天我们一起来分析下&#xff0c;选择稳定的代理IP可以从哪几方面去考虑。 1、代理IP的可用性 代理IP要稳定&#xff0c;先要可以用。一个代理IP池是否稳定&#xff0c;要看代理IP的…

区分服务 DiffServ

目录 区分服务 DiffServ 区分服务的基本概念 区分服务 DiffServ 的要点 每跳行为 PHB DiffServ 定义的两种 PHB 区分服务 DiffServ 区分服务的基本概念 由于综合服务 IntServ 和资源预留协议 RSVP 都较复杂&#xff0c;很难在大规模的网络中实现&#xff0c;因此 IET…

Docker复习笔记

Centos7安装Docker Docker官网:www.docker.com Docker官网仓库:hub.docker.com Docker文档是比较详细的 安装相关依赖 yum -y install gcc gcc-c yum install -y yum-utils 设置docker镜像仓库 yum-config-manager --add-repo https://download.docker.com/linux/centos/do…

Mysql运维篇(五) 部署MHA--主机环境配置

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 大佬博文 https://www.cnblogs.com/gomysql/p/3675429.html MySQL 高可用&#xff08;MHA&#x…