【C++】 类的新成员:static成员和类的好朋友:友元

news2025/1/18 6:55:41

欢迎来到CILMY23的博客

🏆本篇主题为: 类的新成员:static成员和类的好朋友:友元

🏆个人主页:CILMY23-CSDN博客

🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux

🏆感谢观看,支持的可以给个一键三连,点赞关注+收藏。


✨写在前头:

这么长时间,我们终于把构造函数的内容解决了,初始化列表,默认构造函数,构造函数和析构函数的顺序,全缺省的默认构造函数都值得我们细细品味,本期将接触类和对象中新的部分,static成员和类的好朋友:友元


static成员

1.1  static成员的引入

之前我们学过了构造函数的顺序,我们来看看以下代码:

int n = 0;

class A
{
public:
	A()
	{
		++n;
	}

	A(const A& a)
	{
		++n;
	}
private:
};

A Func()
{
	A aa;
	return aa;
}

int main()
{
	A aa1;
	A aa2;
	Func();

	cout << n << endl;
	return 0;
}

稍微分析一下我们就会发现,这是四次的创建,但是有的编译器会优化,可能就是三次,但是不影响我们这里的讨论。如果我们把int n 从全局放到类里面,我们要如何增加次数呢?于是C++里提供了static成员。 

1.2  static成员的概念

在C++中,static关键字在类的中用于声明静态成员。静态成员可以是静态成员变量(也叫静态数据成员)或静态成员函数静态成员是类的一部分,但它们不是类的对象的一部分,属于所有对象,属于所有类。

 ◼️例如:静态成员变量如下

class A
{
public:
	A()
	{
		++n;
	}

	A(const A& a)
	{
		++n;
	}
private:
	//静态成员是类的一部分,但它们不是类的对象的一部分,属于所有对象,属于整个类
	//声明
	static int n;
};

//定义,类中的全局变量
int A::n = 0;

A Func()
{
	A aa;
	return aa;
}

int main()
{
	A aa1;
	A aa2;
	Func();
	return 0;
}

1.3  static成员变量的访问

第一种: 通过类域访问,将private改为public,放开访问权限。

 第二种:提供公有的函数GetN,用来获取私有的成员变量

1.4  static静态成员函数

在上述访问中,如果我们将成员函数GetN加上static,它就变成了静态的成员函数。

class A
{
public:
	A()
	{
		++n;
	}

	A(const A& a)
	{
		++n;
	}
	//static 成员函数没有this指针
	static int GetN()
	{
		//a++ 不能访问其他的
		return n;
	}

private:
	int a;
	static int n;
};

//定义,类中的全局变量
int A::n = 0;

A Func()
{
	A aa;
	return aa;
}

int main()
{
	A aa1;
	A aa2;
	Func();

	cout << aa1.GetN() << endl;
	cout << A::GetN() << endl;

	return 0;
}

注意:静态成员函数没有this指针 ,它也不能访问非静态成员

1.5  static静态成员的特点 

  1. 静态成员所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用  类名::静态成员  或者  对象.静态成员  来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

两个问题: 

1. 静态成员函数可以调用非静态成员函数吗?

答:静态成员函数不能直接调用非静态成员函数。静态成员函数是属于类的,而非静态成员函数是属于类的某个特定对象的。因为静态成员函数在调用时不依赖于类的任何特定对象,它没有this指针,所以它不能直接调用那些依赖于特定对象(即需要通过this指针访问的)的非静态成员函数。

2. 非静态成员函数可以调用类的静态成员函数吗?

 答:非静态成员函数可以调用类的静态成员函数。因为静态成员函数不依赖于类的具体实例,所以它们可以被类的任何成员函数调用,无论是静态的还是非静态的。在非静态成员函数中调用静态成员函数不需要特定的对象实例,可以直接调用。

友元 

前言:

 在前几篇中,我们就涉及过了友元,无论是在写日期计算器(链接),还是在写赋值运算符重载(链接)的时候,友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

2.1 友元概念

 友元(Friend)是C++中的一个关键概念,它允许某些特定的外部函数或类访问另一个类的私有(private)或保护(protected)成员。友元破坏了类的封装性,但在某些情况下能提供方便的访问方式。友元又分为:友元函数友元类

  1. 友元函数: 当某个函数被声明为一个类的友元时,这个函数就可以访问该类的所有成员,包括私有和保护成员。友元函数不是类的成员函数,它可以是任何普通函数,甚至可以是另一个类中的成员函数。

  2. 友元类: 如果一个类被声明为另一个类的友元,那么这个友元类的所有成员函数都可以访问另一个类的私有和保护成员。这种关系在两个密切相关的类之间非常有用,例如,在实现某些设计模式时。

 2.2 友元函数

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

友元函数:

 

//Date.h
//用户输出
ostream& operator<<(ostream& out,const Date& d);
//用户输入
istream& operator>>(istream& in, Date& d);

//Date.cpp
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "天" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	
	while (1)
	{
		cout << "请输入对应的年月日" << endl;
		in >> d._year
			>> d._month
			>> d._day;
		if (!d.CheckInvalid())
		{
			cout << "日期输入错误,请重新输入" << endl;
		}
		else
		{
			break;
		}
	}
 
	return in;
}

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

友元函数的特点:

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

2.3 友元类 

 比较亲近的两种类,例如日期类和时间类,例如:

class Time
{
	friend class Date;
	// 声明日期类为时间类的友元类,则在日期类中就直接访问Time类 中的私有成员变量
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;
};

友元类的特点:

#️⃣友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员

1️⃣友元关系是单向的,不具有交换性。
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

2️⃣友元关系不能传递
如果C是B的友元, B是A的友元,则不能说明C时A的友元。

3️⃣友元关系不能继承


💡总结

1️⃣ 静态成员是类的一部分,但它们不是类的对象的一部分,属于所有对象,属于所有类。

2️⃣ 静态成员函数没有this指针 ,它也不能访问非静态成员

3️⃣ 友元还是要慎用,因为它突破了封装,提供了一个“后门”

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

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

6️⃣友元关系是单向的,不具有交换性,友元关系不能传递也不能继承 


感谢各位同伴的支持,本期C++就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

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

相关文章

【数据分析面试】43.寻找给小费最多的客人(Python:字典用法)

题目&#xff1a; 寻找给小费最多的客人 &#xff08;Python) 给定两个非空列表user_ids和tips&#xff0c;编写一个名为most_tips的函数&#xff0c;用于找到给小费最多的客户。 示例&#xff1a; 输入&#xff1a; user_ids [103, 105, 105, 107, 106, 103, 102, 108, 1…

利用香港多IP服务器优化网站访问速度的关键策略?

利用香港多IP服务器优化网站访问速度的关键策略? 随着数字化时代的不断发展&#xff0c;网站的全球访问速度成为企业吸引用户、提升竞争力的重要因素。特别对于跨国企业而言&#xff0c;如何确保全球用户都能享受到稳定快速的访问体验显得尤为重要。在这一背景下&#xff0c;…

MySQL文档_下载

可能需要&#xff1a;MySQL下载–》更新版本–》迁移数据库到MySQL 以下都不重要【只要确定好需要安装版本&#xff0c;找到对应的版本下载&#xff0c;安装&#xff0c;设置即可】 下载、安装&#xff1a; Determine whether MySQL runs and is supported on your platform…

【TOP-CCF】影响因子8.0-9.0,仅4天见刊!1区,国人友好,稳定检索32年

本周投稿推荐 SSCI • 2区社科类&#xff0c;3.0-4.0&#xff08;社科均可&#xff09; EI • 计算机工程类&#xff08;接收广&#xff0c;录用极快&#xff09; SCI&EI • 4区生物医学类&#xff0c;1.5-2.0&#xff08;录用率99%&#xff09; • 1区工程类&#…

在线caj转换成pdf免费吗?caj变成pdf很容易!点进来!

在数字化阅读日益盛行的今天&#xff0c;各种电子文献格式层出不穷&#xff0c;其中CAJ和PDF无疑是两种最为常见的格式。CAJ是中国知网推出的一种专用全文阅读格式&#xff0c;而PDF则因其跨平台、不易被修改的特性&#xff0c;受到了广大读者的青睐。因此&#xff0c;将CAJ格式…

C语言中的混合运算

1 混合运算 类型强制转换场景 整型数进行除法运算时&#xff0c;如果运算结果为小数&#xff0c;那么存储浮点数时一定要进行强制转换。例子&#xff1a; #include <stdio.h> //运算强制转换 int main(void) {int i5;//整型float ji/2;//这里做的是整型运算&#xff0…

clion设置中文和背景图片以及破解

1.效果如下 2.下载最新版clion window下的clion下载 第一个exe和第二个zip都行&#xff0c;推荐exe具体安装不解释&#xff0c;请参考其他教程 3.汉化 英语观看不方便&#xff0c;可以使用插件汉化。在设置》插件&#xff08;plugins&#xff09;>Marketplace下的Chine…

EFCore_创建项目

添加依赖 Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools(Migration工具) 根据使用的DB添加对应依赖&#xff1a; SQL Server&#xff1a;Microsoft.EntityFrameworkCore.SqlServer 添加该依赖时可不添加Microsoft.EntityFrameworkCore&#xff0c;该依…

肺部营养“救星”,让每次呼吸更自由

​#肺科营养#朗格力#班古营养#复合营养素#肺部营养# 正常的健康人,每天自由幸福的呼吸。但是对于肺病患者来说,特别是慢阻肺人群,每一次呼吸都可能是一场挑战,每一口气都显得弥足珍贵。 肺病患者号称沉默的“呼吸杀手”,它虽然沉默,但不代表它没能力,除了引起肺功能下降,氧气…

工业无风扇计算机的优点

无风扇计算机往往采用紧凑且密封的外形&#xff0c;使其坚固耐用&#xff0c;使其能够在需要现场工程师进行维护之前承受恶劣的环境数年。机载移动部件较少或没有移动部件会降低组件无法按预期运行的可能性&#xff0c;或者更糟糕的是发生故障和损坏。采用工业组件和较低的散热…

rabbitmq交换机,死信队列的简单例子

假设我们有一个场景&#xff0c;生产者有消息发到某个直连交换机&#xff0c;这个交换机上有两个队列分别存储两种类型的消息&#xff0c;但是与这两个队列相连的消费者太不争气了&#xff0c;处理消息有点慢&#xff0c;我们想5秒钟这个消息在队列中还没有被消费的话&#xff…

初识java——javaSE(4)类与对象

文章目录 前言一 类与对象1.1 面向过程与面向对象思想的区别&#xff1a;1.2 类的定义1.3 类的实例化——对象通过创建对象&#xff0c;调用对象中的成员变量与方法 1.4 this关键字this的作用一&#xff1a;this 的作用二构造方法&#xff1a;对象创建的两步方法的重载 this的作…

基础ArkTS组件:输入框,开关,评分条(HarmonyOS学习第三课【3.3】)

输入框组件 ArkUI开发框架提供了 2 种类型的输入框&#xff1a; TextInput 和 TextArea &#xff0c;前者只支持单行输入&#xff0c;后者支持多行输入&#xff0c;下面我们分别做下介绍。 TextInput 子组件 无 接口 TextInput(value?:{placeholder?: ResourceStr, tex…

Echarts结课之小杨总结版

Echarts结课之小杨总结版 前言基础回顾框架sale框架代码&#xff1a; user框架基础代码&#xff1a; inventory框架基础代码&#xff1a; total框架基础代码&#xff1a; 基础设置1.标题(Title)2.图例(Legend)实现 3.工具提示(Tooltip)实现 4.X轴(X Axis) 和 Y轴(Y Axis)5.数据…

架构设计入门(Redis架构模式分析)

目录 架构为啥要设计Redis 支持的四种架构模式单机模式性能分析优点缺点 主从复制&#xff08;读写分离&#xff09;结构性能分析优点缺点适用场景 哨兵模式结构优点缺点应用场景 集群模式可用性和可扩展性分析单机模式主从模式哨兵模式集群模式 总结 本文主要以 Redis 为例&am…

【Python |基础入门】入门必备知识(基础各方面全覆盖)

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

Linux —— 线程控制

Linux —— 线程控制 创建多个线程线程的优缺点优点缺点 pthread_self进程和线程的关系pthread_exit 线程等待pthread_ join线程的返回值线程分离pthread_detach 线程取消pthread_cancel pthread_t 的理解 我们今天接着来学习线程&#xff1a; 创建多个线程 我们可以结合以前…

图搜索算法-最短路径算法-贝尔曼-福特算法

相关文章&#xff1a; 数据结构–图的概念 图搜索算法 - 深度优先搜索法&#xff08;DFS&#xff09; 图搜索算法 - 广度优先搜索法&#xff08;BFS&#xff09; 图搜索算法 - 拓扑排序 图搜索算法-最短路径算法-戴克斯特拉算法 贝尔曼-福特算法&#xff08;Bellman-Ford&#…

树莓派 4B putty远程连接登录显示拒绝访问,密码修改

putty显示拒绝访问 可能是树莓派的ip没有找到正确的 在下载系统镜像的时候&#xff0c;会提示设置wifi 这里设置的WiFi和密码需记住&#xff0c;主机名也需记住 可以在手机打开热点&#xff08;将热点的账号和密码改为跟你设置的wifi一样的&#xff09; 可以在手机后台查看…

Linux系统的第六天

昨天&#xff0c;学习了vim编辑工具&#xff0c;今天学习Linux系统的目录结构、补充命令和配置网络。 一、目录结果 1.1目录的特点 Windows和Linux&#xff1a; Windows中c、d、e盘&#xff0c;每个都是一个根系统【多根系统】&#xff1b;Linux中只有一个根【单根系统…