类和对象(C++)( static成员、explicit、友元、内部类、匿名对象)

news2024/11/19 9:40:44

类和对象

  • static成员
    • 概念
    • static成员“登场”
    • 特性
      • static成员使用
    • 注意
  • explicit
    • 从一段代码引入explicit
    • 和explicit相关特性
  • 友元
    • 友元函数
      • 引入
        • 问题
        • 解决
      • 小结
    • 友元类
  • 内部类
    • 概念
    • 特性
  • 匿名对象
    • 引入
    • 使用

static成员

概念

类的静态成员:声明为static的类成员。
静态成员变量:用static修饰的成员变量。
静态成员函数:用static修饰的成员函数。

注意:静态成员变量要在类外进行初始化

static成员“登场”

class A
{
public:
	A(){
		++_scount;
	}
	A(const A& t){
		++_scount;
	}
	~A(){
		--_scount;
	}

	//出现这个静态成员函数,是因为_scount是私有的,类外不能访问
	static int GetCount()
	{
		return _scount;
	}

private:
	//非静态成员变量的默认值给初始化列表。
	//静态成员变量没有初始化列表,所以不能给默认值。--> 没有this指针
	static int _scount;
};

//全局定义,不能像成员变量一样在初始化列表定义
int A::_scount = 0;

int main()
{
	cout << A::GetCount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetCount() << endl;
	return 0;
}

特性

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

static成员使用

//设计一个类,在类外面只能在栈和堆上创建对象
class A
{
public:
	//在私有化构造函数的同时,在类中创建了两个静态成员函数,用来调用创建在栈和堆上的对象
	
	//栈
	static A GetStackObj()
	{
		A aa;
		return aa;
	}
	//堆
	static A* GetHeapObj()
	{
		return new A;
	}

private:
	//把构造函数私有化,因为创建对象就要调用构造函数
	A(){}
private:
	int _a1 = 1;
	int _a2 = 2;
};

int main()
{
	//static A aa1;   //静态区
	//A aa2;          //栈区
	//A* ptr = new A; //堆区

	A* ptr = A::GetHeapObj();
	cout << ptr << endl;
	A::GetStackObj();
	return 0;
}

注意

  1. 静态成员函数不能调用非静态成员。原因:没有this指针,无法在内部调用成员操作。
  2. 非静态成员函数可以访问类的静态成员。
  3. 静态变量也可以是自定义类型成员

成员变量和静态成员变量的区别
成员变量:属于每一个类对象,存储对象里
静态成员变量:属于类,属于类的每个对象共享,存储在静态区。(特性第一条)

explicit

从一段代码引入explicit

class A
{
public:
	A(int a)
		:_a(a)
	{}

private:
	int _a;
};

int main()
{
	A aa1(1);
	A aa2 = 2;
}

代码分析:
代码分析

和explicit相关特性

  1. 构造函数不仅可以构造和初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
  2. 无论单参还是除第一个参数无默认值其余均有默认值的 构造函数,被explicit修饰,该构造函数久不具备类型转换的作用

友元

提供了一种突破封装的方式,提供了便利的同时,破坏了封装。不宜多用

友元函数

引入

问题

在重载 <<(流插入)和 >>(流提取)运算符时,发现把该运算符重载成成员函数,不符合正常使用规则。因为cout输出流对象和隐含的this指针抢占第一个参数的位置。this指针默认是第一个参数(左操作数),但调用时cout需要是第一个形参对象。

eg:

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

	//因为成员函数第一个参数一定是this,所以d必须放在左侧
	//d << cout; -> d.operator<<(&d, cout);   //但是这样不符合调用流插入操作符的常规
	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}

private:
	int _year;
	int _month;
	int _day;
};

解决

将 <<(流插入)和 >>(流提取)运算符重载成全局函数。但是会产生另一个问题,在类外没办法访问类里的成员。这时出现了友元函数。

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}

istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year >> d._month >> d._day;
	return _cin;
}

int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

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

小结

  • 友元函数可以访问类的私有成员和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰。原因:没有this指针
  • 友元函数可以在类的任何地方声明,不受访问限定符限制
  • 一个函数可以是多个类的友元
  • 友元函数的调用和普通函数的原理一致

友元类

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

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类的私有成员,反过来,Time类不能访问Date类的私有成员。

内部类

概念

一个类定义在另一个类内部,这个在内部的类就是内部类。

注意:

  1. 内部类是一个独立的类,不属于外部类,不能通过外部类的对象去访问内部类的成员,外部类对内部类没有任何优越的访问权限
  2. 内部类是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类的所有成员。但外部类不是内部类的友元

特性

  1. 内部类可以定义在外部类的public、protected、private。但是内部类受外部类访问限定符限制
  2. 内部类可以直接访问外部类的static成员,不需要外部类的对象或类名
  3. sizeof(外部类) = 外部类。和内部类没有关系

eg:

class A
{
public:
	class B  //B天生就是A的友元
	{
	public:
		void F(const A& a)
		{
			cout << k << endl;
			cout << a.h << endl;
		}
	private:
		int b;
	};
private:
	static int k; 
	int h;
};
int A::k = 1;
int main()
{
	//静态变量不被计算在类的大小中。
	//静态变量属于类不属于实列,无论创建多少个类的实列,静态变量始终只占用一块内存
	cout << sizeof(A) << endl;  //4 

	//B b; 不能直接这样定义
	A::B b;
	b.F(A());
	return 0;
}

匿名对象

引入

匿名对象特征:

  1. 匿名对象不用起名字。
  2. 匿名对象的声明周期只有定义的一行,下一行他就会自动调用析构。
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

private:
	int _a;
};

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

使用

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

private:
	int _a;
};

class Solution
{
public:
	int Sum_Solution(int n)
	{
		return n;
	}
};

int main()
{
	//匿名对象使用场景
	Solution().Sum_Solution(10);

	//A& ra = A(1);    //err  匿名对象具有常性
	
	//使用const引用会延长匿名对象的生命周期,生命周期变成当前对象的局部域,
	//相当于引用的生命周期
	const A& ra = A(1);//ok
	return 0;
}

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

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

相关文章

【黑客】网络安全靠自学?只会毁了你!

1️⃣网安现状 ❗本文面向所有 想要涉足网安领域 或 已经涉足但仍处在迷茫期 的伙伴&#xff0c;如果你月薪达到了3w&#xff0c;那么请你离开。 如果没有&#xff0c;希望你继续看下去&#xff0c;因为你人生的转折点将从这篇文章开始。 ✈️网络安全&#xff0c;一个近几年大…

5 个能出色完成数据恢复的免费数据恢复软件知识分享。

有时&#xff0c;由于意外删除或某些问题&#xff0c;您可能会丢失 Windows 10 笔记本电脑或台式机上的重要数据。Windows 操作系统不提供任何内部工具来恢复已删除的数据。但是有一些非常好的数据恢复软件可以更专业地完成这项工作。最好的人总是有报酬的&#xff0c;但不用担…

按键精灵、auto.js等一些移动端脚本 如何连接云服务器的数据库, 进行读写操作

一、技术背景 按键手机版和auto.js&#xff0c;只支持连接本地数据库sqllite&#xff0c;该数据库只存在本地 其他设备无法读写&#xff0c;就像本地的txt一样。 而很多脚本作者的需求是&#xff1a;多个脚本&#xff0c;甚至在全国不同城市的脚本也能读取和写入同一批数据&…

AJAX-day01

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 AJAX 概念和 axios 使用 什么是 AJAX 怎么用 AJAX &#xff1f; axios 使用 认识 URL 什么是 URL&…

韦东山Linux教学视频中的makefile文件详细介绍

前言 &#xff08;1&#xff09;在学习韦东山Linux教学视频的时候&#xff0c;他的makefile并没有做详细的介绍。以至于我学了很长时间对他的makefile文件不理解。所以本文将会详细介绍韦东山Linux教学视频中的makefile文件含义。 &#xff08;2&#xff09;注意&#xff1a;我…

使用 docker-compose 部署 Jenkins

注&#xff1a;我是在虚拟机&#xff08;Ubuntu&#xff09;上部署了 docker-compose&#xff0c;然后才使用 docker-compose 部署 Jenkins&#xff01; 关于如何在 Ubuntu 部署 docker-compose&#xff0c;可以看我其它的文章。 本文目录 1. 创建 docker_jenkins_compose 目录…

【NI USRP】每一个USRP是如何命名的呢,和原厂Ettus型号有什么关联呢?

详细的硬件配置&#xff0c;非常有助于设备的选型。 如果您采购了X310子板&#xff0c;是可以将其转化为对应的USRP型号的设备。 B系列 EttusNI-USRP频段最大带宽通道B200mini无70 MHZ - 6 GHZ56 MHz1X1B200mini-i无70 MHZ - 6 GHZ56 MHz1X1B205mini-i无70 MHZ - 6 GHZ56 MHz…

三菱以太网通讯模块在哪

捷米特JM-ETH-FX采用工业级设计&#xff0c;导轨安装&#xff0c;带通讯线。不占用PLC编程口&#xff0c;上位机通过以太网对PLC数据监控的同时&#xff0c;触摸屏可以通过复用接口X2与PLC进行通讯。捷米特JM-ETH-FX支持工控领域内绝大多数SCADA软件&#xff0c;支持三菱MC以太…

C#开发的OpenRA游戏之维修按钮

C#开发的OpenRA游戏之维修按钮 前面分析物品的变卖按钮,如果理解这个流程,再看其它按钮的流程,其实是一样的,所以前面的文章是关键,只有理解通透的基础之上,才能继续往下。 维修按钮的存在价值,就是当建筑物受到敌方破坏,还没有完全倒掉之前,可以使用金币来进行修理。…

java项目之电子商城系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的电子商城系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&…

对抗业务逻辑攻击:传统安全工具为何失效

随着数字环境的不断发展&#xff0c;不良行为者寻求利用应用程序漏洞的策略也在不断发展。最阴险的攻击类型之一是业务逻辑攻击 (BLA)。与可以通过签名或模式识别的已知攻击&#xff08;例如 SQL 注入攻击&#xff09;不同&#xff0c;BLA 针对应用程序内的核心功能和决策过程。…

python_股票增加控制人与流通股东等筛选条件

目录 写字前面&#xff1a; 结果展示 获取数据 行业数据 控制人数据 十大流通股东数据 开始合并 1 从行业数据中提取证券股的行业数据 2 合并控制人数据 3 合并十大流通股东 4 把三个结果按列合并 写字前面&#xff1a; 在分析数据的时候&#xff0c;常常需要的字段…

Hippo4j监控RabbitMQ框架的线程池

&#x1f680; 线程池管理工具-Hippo4j &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#…

【分布式系统管理框架】Zookeeper集群

分布式系统管理框架 1. Zookeeper1.1 Zookeeper概述1.2 Zookeeper工作机制1.3 Zookeeper特点1.4 Zookeeper数据结构1.5 Zookeeper应用场景1.6 Zookeeper选举机制 2.部署Zookeeper集群3. 知识点总结3.1 zookeeper3.2 zookeeper选举机制 1. Zookeeper 1.1 Zookeeper概述 Zookee…

什么是微服务架构

什么是微服务架构&#x1f349; 你考虑过吗&#xff1f;什么是微服务&#xff0c;为什么越来越多的企业&#xff0c;为了使自己构建的应用满足客户的期望&#xff0c;而和微服务架构进行整合呢&#xff1f; 微服务&#xff0c;又叫微服务架构&#xff0c;是一种软件架构方式。…

web-报错注入

必要的函数 rand select rand(0) from hackbiao; rand(0)&#xff1a;生成以0开头的随机数&#xff0c;生成的数量与字段下数据的条数相等。如果i没有这个地段的话&#xff0c;就会自己形成一个新的字段打印出来。 count和group by grouip by在进行排序的时候&#xff0c;会…

网络线程模型

堵塞IO模型&#xff1a;每个连接都由独立的线程进行处理。当并发度较高时系统资源占用较大&#xff0c;并且如果线程发生了IO堵塞还会浪费线程资源Reactor模型&#xff1a;reactor线程监听&#xff0c;并分发事件给相应的handlerProactor模型&#xff1a;交由系统进行异步处理&…

海岸带地物分类步骤

1.读取图像 使用 Envi 打开 imageKSC.tif 影像。在 Toolbox 工具栏中选择 Spectral->Build 3D Cube。在 3D Cube File 对话框中选择高光谱数据集&#xff0c;显示信息为 614*512*176 的高光谱影像&#xff0c;单击 OK 按钮。 图1 原始影像 2.选择波段 当打开 3D Cube RGB…

垃圾回收的核心知识点解析

目录 检测垃圾引用计数算法可达性分析算法 回收垃圾标记清除算法复制算法标记整理算法分代算法 Java运行时内存中的程序计数器、虚拟机栈、本地方法栈这三部分区域其生命周期与相关线程有关&#xff0c;随线程而生&#xff0c;随线程而灭。而程序计数器就是一个单纯存地址的整数…