【C++初阶】类和对象(下)之友元 + 内部类 + 匿名对象

news2024/12/24 3:06:26

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨


目录

  • 一、友元
    • 1.1 友元函数
      • 1.11 友元函数特性
      • 1.12 为什么不推荐使用友元
    • 1.2 友元类
      • 1.21 友元类的特性
  • 二、内部类
    • 2.1 内部类的特性
  • 三、匿名对象
    • 3.1 匿名对象的特性

一、友元

友元提供了一种 突破封装 的方式。友元分为:友元函数和友元类。

1.1 友元函数

我们在实现日期类的时候就用到了友元函数。重载operator<<时,发现没办法将operator<<重载成成员函数,因为成员函数的第一个参数通常是一个指向当前对象的this指针。而cout
输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。因此只能将operator<<重载成全局函数。但这又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。

#include <iostream>
using namespace std;

class Date
{
public:
	// 友元声明
	// (以下两个函数可以使用类中的成员变量)
	friend istream& operator>>(istream& cin, Date& x);
	friend ostream& operator<<(ostream& cout, const Date& x);

private:
	int Year;
	int Month;
	int Day;
};

istream& operator>>(istream& cin, Date& x)
{
	cin >> x.Year >> x.Month >> x.Day;
	return cin;
}

ostream& operator<<(ostream& cout, const Date& x)
{
	cout << x.Year  << "年" << x.Month << "月" << x.Day << "日";
	return cout;
}

int main()
{
	Date d1;
	cin >> d1;
	cout << d1 << endl;

	return 0;
}

【结果展示】

在这里插入图片描述

1.11 友元函数特性

  1. 友元函数可访问类的私有和保护成员,但不是类的成员函数

这是因为成员函数是通过类的对象来调用的,必须要有对象才能调用成员函数。而友元函数并不属于类的成员函数,因此不能直接访问类的成员函数。

  1. 友元函数不能用const修饰

友元函数是在类的外部定义的它能够访问类的私有成员。而 const 关键字表示成员函数不会修改该对象的状态,但是友元函数并没有绑定到任何对象上,也不受类的访问控制,所以 const 修饰符对友元函数没有意义。

  1. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  2. 一个函数可以是多个类的友元函数
  3. 友元函数的调用与普通函数的调用原理相同

1.12 为什么不推荐使用友元

  • 首先,友元打破了封装性原则:使得类的实现细节暴露给了外部,增加了代码的复杂度和难度。
  • 友元关系是单向的,如果需要访问多个类的私有成员,就需要在每个类中都进行友元声明,这会增加代码维护的难度。
  • 最后,友元破坏了类的继承关系,子类无法继承基类中的友元关系,从而限制了代码的可维护性和可扩展性。
  • 因此,尽管友元在某些情况下可以提供便利,但在一般情况下,不推荐使用友元

1.2 友元类

#include <iostream>
using namespace std;

class 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;
};
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;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

以上代码在Time类中声明Date类的友元类,则在Date类中就直接访问Time类

1.21 友元类的特性

  1. 友元关系是单向的,不具有交换性。

比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行

  1. 友元关系不能传递

如果CB的友元, BA的友元,不能说明CA的友元。

  1. 友元关系不能继承

二、内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。

#include <iostream>
using namespace std;

class A
{
public:
	// B是A的内部类
	class B 
	{
	public:
		void foo(const A& a)
		{
			
		}
	};
private:
	static int k;
	int h;
};
// static成员变量的定义方式
int A::k = 1;

2.1 内部类的特性

  1. 内部类可以定义在外部类的publicprotectedprivate都是可以的
  2. 内部类是一个独立的类,它不属于外部类,注意:不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限
  3. 内部类就是外部类的友元类内部类可以通过外部类的对象参数来访问外部类中的所有成员。(总之,内部类可以访问外部类中的所有成员,而外部类不行)。并且内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名
#include <iostream>
using namespace std;

class A
{
public:
	A(int i = 3)
		:h(i)
	{

	}
	// B是A的内部类
	class B 
	{
	public:
		void foo(const A& a)
		{
			// 内部类可以直接访问外部类中的static成员
			cout << k << endl;
			// 内部类可以访问外部类中的所有成员
			cout << a.h << endl;
		}
	};
private:
	static int k;
	int h;
};
// static成员变量的定义方式
int A::k = 1;

int main()
{
	A a1;
	A::B b; //内部类的定义方式
	
	b.foo(a1);

	return 0;
}

【程序结果】

在这里插入图片描述

  1. sizeof(外部类) = 外部类,和内部类没有任何关系
#include <iostream>
using namespace std;

class A
{
public:
	A(int i = 3)
		:h(i)
	{

	}
	// B是A的内部类
	class B 
	{
	public:
		void foo(const A& a)
		{
			// 内部类可以直接访问外部类中的static成员
			cout << k << endl;
			// 内部类可以访问外部类中的所有成员
			cout << a.h << endl;
		}
	};
private:
	static int k;
	int h;
};
// static成员变量的定义方式
int A::k = 1;

int main()
{
	cout << sizeof(A) << endl;

	return 0;
}

【程序结果】
在这里插入图片描述

注意:static修饰的成员变量不需要计算。因为静态成员变量属于类,属于类的每个对象共享,不属于某个具体的对象,存储在静态区。

三、匿名对象

匿名对象的特点 不用取名字

#include <iostream>
using namespace std;

class A
{
public:
	// 构造函数
	A(int i)
		:a(i)
	{
		cout << "调用构造" << endl;
	}
	// 析构函数
	~A()
	{
		cout << "调用析构" << endl;
	}
private:
	int a;
};

int main()
{
	A(2); // 匿名对象
	A a(1); // 有名对象
	
	return 0;
}

但是匿名对象的生命周期只有一行,我们可以看到下一行他就会自动调用析构函数,而有名函数的声明周期是当前函数的局部域。

在这里插入图片描述

3.1 匿名对象的特性

  1. 匿名对象具有常属性

在这里插入图片描述

  1. const引用匿名对象,生命周期就就和有名对象一样:当前函数的局部域

在这里插入图片描述

A(2)首先会调用拷贝构造,然后就再屏幕上打印“调用构造”,紧接着由于类型转换,中间会生成临时变量,而临时变量同样也是具有常属性的,然后临时变量再拷贝构造给x。所以,这应该调用两次构造,而为什么只调用了一次呢?原因是:对于这种连续的构造,编译器会直接优化用直接构造,提高效率。

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

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

相关文章

一台服务器通过nginx安装多个web应用

1.首先安装nginx网站服务器 yum install nginx 2.nginx 的主配置文件&#xff1a;/etc/nginx/nginx.conf (一台服务器有两个域名部署) 我们在/etc/nginx/nginx.d/下创建一个conf文件&#xff0c;这个文件会被嵌套到主配置文件当中 server { listen 80; …

《数据库应用系统实践》------ 个人作品管理系统

系列文章 《数据库应用系统实践》------ 个人作品管理系统 文章目录 系列文章一、需求分析1、系统背景2、 系统功能结构&#xff08;需包含功能结构框图和模块说明&#xff09;3&#xff0e;系统功能简介 二、概念模型设计1&#xff0e;基本要素&#xff08;符号介绍说明&…

Netty客户端与服务器端闲暇检测与心跳检测(三)

网络应用程序中普遍存在一个问题&#xff1a;连接假死&#xff0c;连接假死现象是:在某一端(服务器端|客户端)看来,底层的TCP连接已经断开,但是应用程序没有捕获到,因此会认为这个连接还存在。从TCP层面来说,只有收到四次握手数据包,或者一个RST数据包,才表示连接状态已断开; 连…

Spring练习二ssm框架整合应用

导入教程的项目&#xff0c;通过查看源码对aop面向切面编程进行理解分析 aop面向编程就像是我们给程序某些位置丢下锚点&#xff08;切入点&#xff09;以及当走到锚点时需要调用的方法&#xff08;切面&#xff09;。在程序运行的过程中&#xff0c; 一旦到达锚点&#xff0c;…

f-stack的源码编译安装

DPDK虽然能提供高性能的报文转发&#xff08;安装使用方法见DPDK的源码编译安装&#xff09;&#xff0c;但是它并没有提供对应的IP/TCP协议栈&#xff0c;所以在网络产品的某些功能场景下&#xff08;特别是涉及到需要使用TCP协议栈的情况&#xff09;&#xff0c;比如BGP邻居…

Ansible原理简介与安装篇

工作原理 1、在Ansible管理体系中&#xff0c;存在“管理节点”和“被管理节点” 2、被管理节点通常被称为”资产“ 3、在管理节点上&#xff0c;Ansible将AdHoc或PlayBook转换为python脚本。并通过SSH将这些python脚本传递到被管理服务器上。在被管理服务器上依次执行&#xf…

遥感云大数据在灾害、水体与湿地领域及GPT模型应用

近年来遥感技术得到了突飞猛进的发展&#xff0c;航天、航空、临近空间等多遥感平台不断增加&#xff0c;数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量猛增&#xff0c;遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇&#xf…

基础篇010.2 STM32驱动RC522 RFID模块之二:STM32硬件SPI驱动RC522

目录 基础篇010.1 STM32驱动RC522 RFID模块之一&#xff1a;基础知识 1. 实验硬件及原理图 1.1 RFID硬件 1.2 硬件原理图 2. 单片机与RFID硬件模块分析 3. 利用STM32CubeMX创建MDK工程 3.1 STM32CubeMX工程创建 3.2 配置调试方式 3.3 配置时钟电路 3.4 配置时钟 3.5 配…

【C++】Map、Set 模拟实现

文章目录 &#x1f4d5; 概念&#x1f4d5; 实现框架Find()★ 迭代器 ★反向迭代器map 的 operator[ ] &#x1f4d5; 源代码rb_tree.hset.hmap.h &#x1f4d5; 概念 map、set 是 C 中的关联式容器&#xff0c;由于 map 和set所开放的各种操作接口&#xff0c;RB-tree 也都提…

2023.05.28 学习周报

文章目录 摘要文献阅读1.题目2.现有方法存在的局限性3.SR-GNN模型4.模型的组成部分4.1 构图4.2 item向量表示4.3 session向量表示4.4 预测模块 5.实验与分析5.1 数据集5.2 比较方法5.3 评估指标5.4 实验结果 6.结论 有限元法1.一个例子2.进一步 深度学习1.张量场2.对流-扩散方程…

Linux(基础IO详解)

在基础IO这篇博客中&#xff0c;我们将了解到文件系统的构成&#xff0c;以及缓冲区究竟是个什么东东&#xff0c;我们都知道缓冲区&#xff0c;有时也谈论缓冲区&#xff0c;但不一定真的去深入了解过缓冲区。为什么内存和磁盘交互速度如此之慢&#xff1f;为什么都说Linux中一…

Dom解析与Sax解析的区别

1.Dom解析&#xff1a; Dom解析的时候&#xff0c;首先要把整个文件读取完毕&#xff0c;装载到内存中。然后进行解析&#xff0c;在解析的过程中&#xff0c;你可以直接获取某个节点&#xff0c;进行操作&#xff0c;也可以获取根节点然后进行遍历操作&#xff0c;得到所有的…

一台服务器通过apache安装多个web应用

当我们只有一台linux服务器资源但有创建多个网站的需求时&#xff0c;我们可以通过安装一个网站服务器Apache进行搭建&#xff0c;此次服务器使用Centos 7 下面分别介绍一个域名多个端口和多个域名用Apache来搭建多个网站的操作过程。 一、使用apache 服务器 &#xff08;一…

HCIA-MSTP替代技术之链路捆绑(LACP模式)

目录 手工链路聚合的不足&#xff1a; LACP链路聚合的原理 LACP模式&#xff1a; LACPDU&#xff1a; 1&#xff0c;设备优先级&#xff1a; 设备优先级的比较是&#xff1a;先比较优先级大小&#xff0c;0到32768&#xff0c;越小优先级越高&#xff0c;如果优先级相同&a…

华为FinalMLP

FinalMLP:An Enhanced Two-Stream MLP model for CTR Prediction 摘要 Two-Stream model&#xff1a;因为一个普通的MLP网络不足以学到丰富的特征交叉信息&#xff0c;因此大家提出了很多实用MLP和其他专用网络结合来学习。 MLP是隐式地学习特征交叉&#xff0c;当前很多工作…

分布式网络通信框架(二)——RPC通信原理和技术选型

项目实现功能 技术选型 黄色部分&#xff1a;设计rpc方法参数的打包和解析&#xff0c;也就是数据的序列化和反序列化&#xff0c;用protobuf做RPC方法调用的序列化和反序列化。 使用protobuf的好处: protobuf是二进制存储&#xff0c;xml和json是文本存储&#xff1b; pro…

哈希应用: 位图 + 布隆过滤器

文章目录 哈希应用: 位图 布隆过滤器1. 位图1.1 提出问题1.2 位图概念1.3 位图实现1.4 位图应用1.4.1 变形题1代码 1.4.2 变形题21.4.3 找文件交集思路1思路2 1.4.4 总结 1.5 位图优缺点 2. 哈希切割3. 布隆过滤器3.1 提出问题3.2 布隆过滤器概念3.3 布隆过滤器的各个接口3.3.…

MySQL---优化(insert、order by 、group by 、limit、子查询)

1. insert语句优化 当进行数据的insert操作的时候&#xff0c;可以考虑采用以下几种优化方案: -- 如果需要同时对一张表插入很多行数据时&#xff0c;应该尽量使用多个值表的insert语句&#xff0c;这种方式将大大的缩减 -- 客户端与数据库之间的连接、关闭等消耗。使得效率比…

R-Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合实践与拓展

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

ARM体系结构

目录 ARM体系架构 一、ARM公司概述 二、ARM产品系列 三、指令、指令集 指令 指令集 ARM指令集 ARM指令集 Thumb指令集 &#xff08;属于ARM指令集&#xff09; 四、编译原理 五、ARM数据类型 字节序 大端对齐 小端对齐 六、ARM工作模式 1.AR…