【C++】—— 类和对象(一)

news2024/11/18 19:34:19

【C++】—— 类和对象(一)

  • 1、类的定义
  • 2、实例化
    • 2.1、实例化的概念
    • 2.2、对象大小
      • 2.2.1、对象的大小包括什么
      • 2.2.2、内存对齐规则
      • 2.2.3、空类的大小
  • 3、 t h i s this this 指针
  • 4、练习
    • 4.1、题一
    • 4.2、题二

1、类的定义

1.1、类定义

1.1.1、类定义格式

  • c l a s s class class 为定义类的关键字, c l a s s class class 后接类的名字(自己定),{ } 为类的主体,注意类定义结束时,后面的 不能省略

  • 类体中的内容为类的成员:类中的变量称为类的成员变量属性,类中的函数称为类的成员函数方法

  
下面我们简单写一个栈类来感受一下

class Stack
{
public:
	//成员函数
	void Init(int n = 4)
	{
		_a = (int*)malloc(sizeof(int) * n);
		if (nullptr == _a)
		{
			perror("malloc fail");
			exit(1);
		}

		_capccity = n;
		_top = 0;
	}

	void Push(int x)
	{
		// ...扩容
		_a[top++] = x;
	}

	void Destroy()
	{
		fail(_a);
		_a = nullptr;
		_capacity = 0;
		_top = 0;
	}

private:
	//成员变量
	int* _a;
	size_t _capacity;
	size_t _top;
};//分号不能省略

  C++中,并没有规定成员函数和成员变量的位置,只要他们在类中就行,把成员变量混在几个函数的中间也是可以的。但一般来讲都是成员函数在上,成员变量在下。
  

1.1.2、成员变量的标识

  • 为了区分成员变量,一般习惯上成员变量会加上一个特殊的标识,如成员变量前或后加上 _ ;或 m ( m e m b e r ) m(member) m(member) 开头;或 m m m_ 开头。这点C++并没有明确规定,具体看公司的要求

  
  在声明栈类的成员变量时,大家可能发现我在变量名前都加上了 “_”,为什么要这么做呢?
  我们来看一个日期类

class Date
{
public:
	void Init(int year, int month, int day)
	{
		year = year;
		month = month;
		day = day;
	}

private:
	int year;
	int month;
	int day;
};

  可以看到,上述日期类的成员变量与 I n i t Init Init 函数中的形参无法区分,所以为了区分成员变量,要在成员变量前加上特殊的标识
  

1.1.3、C++ 中的 s t r u c t struct struct

  • C++ 中 s t r u c t struct struct 也可以定义类,C++ 中兼容了 C语言 中 s t r u c t struct struct 的用法,同时 s t r u c t struct struct 升级成了
  • 明显的变化是: s t r u c t struct struct 中可以定义函数。 s t r u c t struct struct c l a s s class class 定义类只有一点细微的差别(下面会说),但一般情况下我们还是推荐使用 c l a s s class class 定义类

  
  在C语言,我们定义一个链表的节点,往往是这样定义的:

typedef struct ListNodeC
{
	int val;
	struct ListNode* next;
}ListNodeC;

  
在 C++中, s t r u c t struct struct 升级成了

  1. 类可以定义函数
  2. 名称就可以代表类型,不需要 s t r u c t struct struct + 名称

  

// 不再需要typedef,ListNodeCPP就可以代表类型
struct ListNodeCPP
{
	void Init(int x)
	{
		next = nullptr;
		val = x;
	} 
	
	ListNodeCPP* next;
	int val;
};

  当然,C++ 是兼容 C 的,所以上面的那种方式 C++ 也支持
  

1.1.4、C++ 中的内联函数

  • 在类中定义的成员函数默认是 i n l i n e inline inline,而如果进行声明和定义的分离:声明在类中;定义在类外,则不然。

  

1.1.5、总结

  • c l a s s class class 为定义类的关键字 S t a c k Stack Stack 为类的名字{ } 中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性成员变量;类中的函数称为类的方法或者成员函数
      
  • 为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加 _ 或者 m m m 开头,注意 C++ 中这个并不是强制的,只是一些管理,具体看公司要求
      
  • C++ 中 s t r u c t struct struct可以定义类,C++ 兼容 C 中 s t r u c t struct struct 的用法,同时 s t r u c t struct struct 升级成了类,明显的变化是 s t r u c t struct struct 中可以定义函数,一般情况下我们还是推荐使用 class 定义类
      
  • 定义在类里面的成员函数默认为 i n l i n e inline inline

  

1.2、访问限定符

  可能有小伙伴注意到了,前面定义栈类日期类时,出现了 p u b l i c public public p r i v a t e private private 两个关键字,他们有什么用呢?我们一起来看看

  • C++ 一种实现封装的方式,用类将对象的属性和方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
  • p u b l i c public public 修饰的成员类外可以直接被访问 p r o t e c t e d protected protected p r i v a t e private private 修饰的成员类外不能直接被访问。现阶段我们认为 p r o t e c t e d protected protected p r i v a t e private private 是一样的,以后集成章节才能体现出他们的区别.
  • 访问权限作用域从该访问限定符出现的位置开始,直到下一个访问限定符出现为止,如果后面没有访问限定符,作用域就到 } (收括号)即类结束
  • c l a s s class class 定义成员没有被访问限定符修饰时默认 p r i v a t e private private s t r u c t struct struct 默认 p u b l i c public public 。这也是 c l a s s class class s t r u c t struct struct唯一区别
  • 一般成员变量都会被限制为 p r i v a t e private private/ p r o t e c t e d protected protected,需要给别人使用的成员函数为 p u b l i c public public。当然这只是一般情况,并没有硬性规定

  

在这里插入图片描述

  
举个栗子:

在这里插入图片描述

  当然,一般情况下也没有人会这样写。一般都是公有的放一起,私有的放一起。
  
像这样:

在这里插入图片描述

  
  

1.3、类域

  在C++中,凡是用 { } 括起来的都会形成一个 。类也不例外,类定义了一个新的作用域: 类域,类的所有成员都在类的作用域中。

  不知大家有没有注意到,在前面定义的栈类中,成员函数的命名不再像之前 C语言 写栈时那样要加上栈的标识,如: void STDestroy()。之前 C语言 这样写是因为结构体和函数是分离的,栈叫 D e s t r o y Destroy Destroy ,队列也叫 D e s t r o y Destroy Destroy 就有可能搞混,且同一个域中也不允许出现同名的变量或函数。
  现在他们是栈类的成员函数,在类域之中,即使后面定义的一个队列域有同名的成员函数,也不会冲突。因为名字冲突只发生在同一个域中,不同域可以有相同名字

  那当成员函数的声明和定义分离时,即声明在类内,定义在类的外面,又该如何定义函数呢?

class Date
{
public:
	void Init(int year, int month, int day);


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

void Init(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

  
  我们知道,任何一个变量,编译器都会去找他的出处(声明/定义)。编译器默认只会在全局域或当前函数局部域去找,并不会去类域中找。那怎么办呢?我们告诉他去指定的类域中找就行了。

  • 在类体外定义成员时,需要使用 : : 作用域操作符 指明成员属于哪个类域
class Date
{
public:
	void Init(int year, int month, int day);


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

void Date::Init(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

  这样就行了

  • 类域影响的是编译的查找规则
      
    上述程序 I n i t Init Init 如果不指定类域 D a t e Date Date,那么编译器就把 I n i t Init Init 当成全局函数,那么编译时,找不到 _ y e a r year year 等成员的声明/定义在哪里,就会报错。
    指定类域 D a t e Date Date,就是告诉编译器 I n i t Init Init 是成员函数,在当前域找不到的 _ y e a r year year 等成语,就会到类域中去查找。

  

2、实例化

2.1、实例化的概念

  在讲解类的实例化之前,我们先来思考一个问题

在这里插入图片描述

上述成员变量是声明还是定义呢?

答案是 声明
  对变量来说,到底是声明还是定义是看他是否有开空间开了空间的是定义;没开空间的是声明
  

int main()
{
	Date::_year = 0;
	return 0;
}

  我们直接这样访问是会报错的,因为 _ y e a r year year 只是一个声明,并没有开空间。

  那什么时候开空间呢?
  用该类型实例化出一个对象才是开空间

int main()
{
	Date d1;
	Date d2;
	Date d3;

	return 0;
}

  上述就是类的实例化,类和对象是一对多的关系,一个类可以实例化出多个对象
  
  怎么理解这个实例化呢?我们可以用图纸和实物建筑来类比

在这里插入图片描述

  类就相当于图纸,图纸上有房子上的各种信息,当不能进去住人;而实例化对象就像是依照着图纸将房子盖好,盖好的房子是可以住人的,相当于实例化开了空间。

  

2.2、对象大小

2.2.1、对象的大小包括什么

  在学习 C语言 结构体时,我们知道结构体中就存着成员,这些成员要按照内存对齐的规则去进行计算大小。类的对象中的成员变量也是如此,成员变量是存储在对象中的。
  现在的问题是:成员函数是否是存储在对象中的呢?
答案是:不需要
  
为什么呢?我们用日期类来举例

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

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	// 这⾥只是声明,没有开空间
	int _year;
	int _month;
	int _day;
};
int main()
{
	// Date类实例化出对象d1和d2
	Date d1;
	Date d2;

	d1.Init(2024, 3, 31);
	d1.Print();

	d2.Init(2024, 7, 5);
	d2.Print();

	return 0;
}

  
  上述代码中,示例化出了 d 1 d1 d1 d 2 d2 d2 两个对象
  我们给两个对象的年月日(成员变量)初始化了不同的值,所以他们的成员变量是不一样的,他们要各种存储自己的成员变量,因此成员变量肯定是存储在对象中
  
  那现在的 d 1 d1 d1 d 2 d2 d2 调用 P r i n t Print Print 函数是调用同一个函数还是不同的函数?
  很显然是同一个函数
  既然都是一样的,那在各自的对象中都存一份,是不是太浪费空间了。我要是实例化10000个对象那不是要重复存储10000份?
  我们通过汇编代码可以看到两个对象调用的都是同一个函数
  

在这里插入图片描述
  
两个 c a l l call call 指令, c a l l call call 的地址都是一样的,表明跳转的是同一个函数
  
  在这里插入图片描述
  
c a l l call call 指令跳转到 jmp 指令
  在这里插入图片描述
  
j m p jmp jmp 指令再跳转到函数

  成员函数其实是存在一个公共的区域

  既然函数不存在对象里面,那函数指针有必要存在对象里面吗?
  也是没必要的,原因还是重复存储浪费空间。
  

  • 函数指针是⼀个地址调⽤函数被编译成汇编指令[ c a l l call call 地址],其实编译器在编译链接时,就要找到函数的地址,不是在运⾏时找,只有动态多态是在运⾏时找,就需要存储函数地址,这个我们以后再学习

  

2.2.2、内存对齐规则

类的大小计算和结构体的计算是一样的,这里我们简单回顾一下。详情请看【C语言】——结构体

  • 第一个成员在与结构体偏移量为 0 的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
  • 注意:对齐数 = 编译器默认的一个对齐数与该成员大小的较小值
  • VS 中默认的对齐数是 8
  • 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到之间的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(函嵌套结构体的对齐数)的整数倍

  

2.2.3、空类的大小

class A
{
	public :
	void Print()
	{
		//...
	}
};
int main()
{
	A a;
	cout << sizeof(a) << endl;
	return 0;
}

  现在有一个问题: a a a 的大小是多大呢?
  
运行结果:

在这里插入图片描述

  为什么该对象没有成员变量还有 1 字节的大小呢
  这里的 1 为了占位
  因为如果一个空间对不给,怎么证明这个对象存在过呢,所以这里给了1个空间大小,纯粹是为了占位表示对象存在
  

3、 t h i s this this 指针

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

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2;

	d1.Init(2024, 3, 31);
	d1.Print();

	d2.Init(2024, 7, 5);
	d2.Print();

	return 0;
}

  现在,我们知道 d 1 d1 d1 d 2 d2 d2 调用的都是同一个 I n i t Init Init 函数和 P r i n t Print Print 函数,那既然是同一个函数为什么能打印出各自的成员变量呢?他们是怎么区分 d 1 d1 d1 d 2 d2 d2 的呢?

在这里插入图片描述

  
  C++中,给了一个隐含的 t h i s this this指针 解决这个问题

  • 编译器编译后,类的成员函数默认会在形参的第一个位置,增加一个当前类类型的指针,叫做 t h i s this this指针。比如 D a t e Date Date 类的 I n i t Init Init 的真实原型为: void Init(Date* const this, int year,int month, int day)
  • 类的成员函数中访问成员变量,本质是通过 t h i s this this 指针访问的,如 I n i t Init Init 函数中给 _ y e a r year year 赋值, this->_year = year;
  • C++ 规定不能在实参和形参的位置显示的写 t h i s this this指针(编译时编译器会处理),但是可以在函数体内显示使用 t h i s this this 指针

  
  因此,上述代码底层是这样的:

class Date
{
public:
	void Init(Date* const this, year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}

	void Print(Date* const this)
	{
		cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1;
	Date d2;

	d1.Init(&d1, 2024, 3, 31);
	d1.Print(&d1);

	d2.Init(&d2, 2024, 7, 5);
	d2.Print(&d2);

	return 0;
}

:这只是底层,实际代码是不允许这样写的。因为 t h i s this this 指针不能在实参和形参显示写;但在函数体内可以使用 this 指针
  
  
那么 t h i s this this指针是存在哪一个区域的呢?

在这里插入图片描述

  首先,肯定不是对象里面。因为我们前面讲解对象大小时,并没有计算 t h i s this this 指针
  我们来看, t h i s this this 指针是一个形参,那形参是存在哪里的呢?
  答案是:
  但这答案也不完全对。
  因为 t h i s this this 指针需要频繁调用,因此有些编译器(如VS)会对其进行优化,放在寄存器

  

4、练习

4.1、题一

下面程序的运行结果是?
A、编译报错    B、正常运行    C、运行崩溃

class A
{
	public :
	void Print()
	{
		cout << "A::Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

  首先把 A 排除了,因为上述程序就算出错那也是因为空指针的问题出错,对空指针的解引用什么时候是编译报错呢?
  
  这题的答案:B

  我们来看p->Print();,这句代码转换成汇编指令是: c a l l call call 指令 -> j m p jmp jmp 指令 -> P r i n t Print Print函数;那 P r r i n t Prrint Prrint 函数在哪呢?在公共代码区,并不在对象中;同时 P r i n t Print Print函数需要传递 t h i s this this 指针,这里传的是 p p p,即 n u l l p t r nullptr nullptr
  
  这一切都没有问题。虽然传递了 n u l l p t r nullptr nullptr t h i s this this 指针,但是函数内并没有对其进行解引用
  我们不要看到对象调用函数:p->Print();就以为是对 n u l l p t r nullptr nullptr 进行了解引用,我们要关注代码的底层
  那为什么需要对象取调用呢?因为 P r i n t Print Print 是其成员函数,在其类域之中,它要过编译那关,语法那关

  

4.2、题二

下面程序的运行结果是?
A、编译报错    B、正常运行    C、运行崩溃

class A
{
	public :
	void Print()
	{
		cout << "A::Print()" << endl;
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

答案:C

  这题与上题的区别是 P r i n t Print Print 函数中多了cout << _a << endl;
  前面的步骤都是与上题一样,但到了cout << _a << endl;语句时,要对 t h i s this this 指针进行解引用cout << this->_a << endl;,因为 t h i s this this 指针是空指针,对空指针进行解引用自然就运行崩溃啦

  
  
  
  
  


  好啦,本期关于类和对象的知识就介绍到这里啦,希望本期博客能对你有所帮助。同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!

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

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

相关文章

黑神话悟空游戏什么时候上线能玩 黑神话悟空是哪个公司 苹果电脑能玩黑神话悟空吗

《黑神话&#xff1a;悟空》是一款以中国神话为背景的动作角色扮演游戏。故事取材于中国古典小说“四大名著”之一的《西游记》。 你将扮演一位“天命人”&#xff0c;为了探寻昔日传说的真相&#xff0c;踏上一条充满危险与惊奇的西游之路。 一、《黑神话&#xff1a;悟空》什…

【Linux系统】线程的互斥

互斥 互斥概念 多个线程能够看到的资源称为共享资源&#xff0c;那我们需要对这种资源进行保护&#xff0c;需要用到互斥&#xff01;&#xff01;&#xff01; 见一见多线程访问的问题 --- 抢票问题 int tickets 1000;void route(const std::string& name) {while(tr…

Docker容器的数据管理

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 我们在使用Docker的过程中&#xff0c;往往需要能查看容器内应用产生的数据&#xff0c;或者需要把容器内的数据进行备份&#x…

python学习笔记——数字

一、数字概述 1.Python 数字数据类型用于存储数值。 数据类型是不允许改变的&#xff0c;这就意味着如果改变数字数据类型的值&#xff0c;将重新分配内存空间。 2.可以使用del语句删除一些数字对象的引用。 del var1[,var2[,var3[....,varN]]]3.可以通过使用del语句删除单个或…

【python014】Python爬取并解析潮汐天气简报-潮历数据

1.欢迎点赞、关注、批评、指正&#xff0c;互三走起来&#xff0c;小手动起来&#xff01; 【python014】Python爬取并解析潮汐天气简报-潮历数据&#xff0c;源代码下载【python014】Python爬取并解析潮汐天气简报-潮历数据&#xff0c;源代码下载【python014】Python爬取并解…

Aria2 任意文件写入漏洞

目录 Aria2介绍漏洞描述漏洞复现 Aria2介绍 Aria2是一个在命令行下运行&#xff0c;多协议&#xff0c;多来源下载工具&#xff08;HTTP / HTTPS&#xff0c;FTP&#xff0c;BitTorrent&#xff0c;Metalink&#xff09;&#xff0c;内建XML-RPC用户界面。Aria提供RPC服务器&a…

2.9.GoogLeNet

GoogLeNet ​ 主要解决了什么样大小的卷积核是最合适的&#xff1a;有时使用不同大小的卷积核组合是有利的 1.Inception块 ​ Inception块由四条并行路径组成。 前三条路径使用窗口大小为11、33和55的卷积层&#xff0c;从不同空间大小中提取信息。 ​ 中间的两条路径在输入…

任务管理无忧:2024年最佳7款待办事项管理软件

本文将分享2024年值得关注的7大优质待办事项管理软件&#xff1a;PingCode、Worktile、滴答清单、时光序、好用便签、Todoist、ClickUp。 在寻找完美的待办事项管理工具时&#xff0c;你是否感觉到选择众多却难以决断&#xff1f;无论是保持日程有序&#xff0c;还是优化团队协…

Linux基本用法(上)

1.计算机主要由 硬件和软件 组成 2.操作系统是什么 ? 有什么作用&#xff1f; 操作系统是软件的一类 主要作用是协助用户调度硬件工作&#xff0c;充当用户和计算机之间的桥梁 3.常见的操作系统有哪些? PC端: Windows&#xff0c;Linux,MacOS 移动端: Android&#xff…

UART 通信协议

文章目录 一 简介二 电平标准三 引脚定义四 数据格式五 波特率 一 简介 ​ UART (Universal Asynchronous Receiver/Transmitter)&#xff0c;通用异步收发器&#xff0c;是一种串行、异步、全双工通信协议。 串行&#xff1a;利用一条传输线&#xff0c;将数据一位一位地传送…

YOLOv8改进 | 主干网络 | ⭐重写星辰Rewrite the Stars⭐【CVPR2024】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

vulntarget-a

实际部署之后的win7 ip: 192.168.127.128 具体攻击过程如下 win7 扫描服务 使用fscan扫描win 7中的服务以及漏洞 ./fscan -h 192.168.127.128 扫出来一个ms17-010以及通达oa的漏洞&#xff0c;既然有永恒之蓝的&#xff0c;直接上MSF就行了 msf6 > search ms17-010 msf6…

架子鼓鼓谱制谱什么软件好 Guitar Pro怎么编鼓谱

对那些想学架子鼓又缺乏预算的朋友来说&#xff0c;通过架子鼓谱子软件来模拟学习也是个不错的选择。不过&#xff0c;由于市面上类似的软件过多&#xff0c;许多人都挑花了眼&#xff01;那么&#xff0c;架子鼓谱子软件哪个比较好用呢&#xff1f;下面小编就来推荐几款好用的…

HTML--JavaScript操作DOM对象

目录 本章目标 一.DOM对象概念 ​编辑 二.节点访问方法 常用方法&#xff1a; 层次关系访问节点 三.节点信息 四.节点的操作方法 操作节点的属性 创建节点 删除替换节点 五.节点操作样式 style属性 class-name属性 六.获取元素位置 总结 本章目标 了解DOM的分类和节…

【论文精读】 | 基于图表示的视频抑郁症识别的两阶段时间建模框架

文章目录 0、Description1、Introduction2、Related work2.1 Relationship between depression and facial behaviours2.2 Video-based automatic depression analysis2.3 Facial graph representation 3、The proposed two-stage approach3.1 Short-term depressive behaviour…

18746 逆序数

这个问题可以使用归并排序的思想来解决。在归并排序的过程中&#xff0c;我们可以统计逆序数的数量。当我们合并两个已经排序的数组时&#xff0c;如果左边的数组中的元素&#xfffd;&#xfffd;于右边的数组中的元素&#xff0c;那么就存在逆序&#xff0c;逆序数的数量就是…

力扣SQL50 按分类统计薪水 条件统计

Problem: 1907. 按分类统计薪水 文章目录 思路Code 思路 &#x1f468;‍&#x1f3eb; 参考题解 Code SELECT Low Salary AS category,SUM(CASE WHEN income < 20000 THEN 1 ELSE 0 END) AS accounts_count FROM AccountsUNION SELECT Average Salary category,SUM(C…

DBus快速入门

DBus快速入门 参考链接&#xff1a; 中文博客&#xff1a; https://www.e-learn.cn/topic/1808992 https://blog.csdn.net/u011942101/article/details/123383195 https://blog.csdn.net/weixin_44498318/article/details/115803936 https://www.e-learn.cn/topic/1808992 htt…

Vue3 Pinia的创建与使用代替Vuex 全局数据共享 同步异步

介绍 提供跨组件和页面的共享状态能力&#xff0c;作为Vuex的替代品&#xff0c;专为Vue3设计的状态管理库。 Vuex&#xff1a;在Vuex中&#xff0c;更改状态必须通过Mutation或Action完成&#xff0c;手动触发更新。Pinia&#xff1a;Pinia的状态是响应式的&#xff0c;当状…

JAVA中的异常:异常的分类+异常的处理

文章目录 1. 异常的分类1.1 Error1.2 Exception1.2.1 运行时异常1.2.2 非运行时异常 2.异常的处理2.1 try catch用法2.2 throws和throw的区别 1. 异常的分类 Throwable类&#xff08;表示可抛&#xff09;是所有异常和错误的超类&#xff0c;两个直接子类为Error和Exception分…