C++的第一道门坎:类与对象(二)

目录

一.类中生成的默认成员函数详解

0.类的6个默认成员函数

1.构造函数

1.1概念

1.2特性

2.析构函数

2.1概念

2.2特性

3.拷贝构造函数

3.1概念

3.2特性

3.3拷贝构造的使用方法

4.运算符重载

5.赋值运算符重载

6.const修饰函数

7.取地址及const取地址操作符重载

二.struct和class的对比

1struct

1.1struct的成员

 1.1.2结构体的默认访问权限

 1.1.3访问权限控制

1.2.class

1.3结构体Struct和类Class之间的区别以及各自使用场景 


一.类中生成的默认成员函数详解

0.类的6个默认成员函数

编译器会给类生成六个默认成员函数,在类中即使我们什么都不做,也会自动生成。

默认成员函数:用户没有显式实现,编译器会自动生成的成员函数称为默认成员函数。

下面我们逐个来讲解这些函数。 

1.构造函数

1.1概念

对于以下Date类: 

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;
};

对于我们写的这个类来说,我们使用时需要用Init的公有方法给对象设置日期,但是如果我们每次都要使用Init方法给对象设置日期信息,未免有些过于繁琐,那么有没有办法能够在对象创建时就将信息设置进去呢?

构造函数即可完成这件事情。

构造函数是一个特殊的成员函数,它的名字和类名相同,在创建类类型对象时编译器会自动调用,以保证每个数据成员都有一个合适的初始值,并且在对象整个生命周期内只调用一次

1.2特性

构造函数虽然叫构造函数,但其作用并不是开一个空间来创建对象而是初始化对象

其特征如下:

  • 函数名与类名相同
  • 无返回值
  • 对象实例化时编译器会自动调用相应的构造函数
  • 构造函数可以重载

下面我们来验证一下以上四个特性:

class Date
{
public:Date()//无返回值而且函数名与类名相同{_year = 2024;_month = 5;_day = 28;}Date(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 A;//调用无参构造A.Print();Date B(3, 4, 5);//调用三个参数的构造B.Print();return 0;
}

在上面这段代码中,通过打印,我们可以观察到一个调用了无参构造,一个调用了有参构造。

  • 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义,编译器将不再生成默认构造函数。

可以看到,我们在将构造函数屏蔽了之后,依旧是可以通过编译的,因此当我们不显式定义构造函数时,编译器会自动生成默认构造函数。 

现在我们执行下这段代码

我们发现了一个奇怪的现象,这里生成了随机值,那么默认构造函数做了什么事呢?

答案:C++将类型分为了内置类型和自定义类型,内置类型就是语言提供的类型,而自定义类型则是我们使用class/union/struct等关键字自己定义的类型。

而默认构造函数会对自定义类型成员调用它的默认构造函数。

我们可以用以下代码验证一下:

class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:int _year;int _month;int _day;Time _a;
};

我们在main函数中初始化了一个Date类型的对象,而Date类型的对象中声明了一个Time类型的对象,由于我们没有写Date类的默认构造函数,因此它会调用编译器自动生成的默认构造函数,这时默认的构造函数所作的事情就是去调用Date类中的自定义类型的构造函数。而Time类的构函数中打印了Time(),因此这段程序的最终输出结果为上图所示。

注意点:在C++11版本中,为我们无法对内置类型生成默认构造的问题打了一个补丁,我们可以在声明时给一个缺省值。

如下图所示

无参的构造函数和全缺省的构造函数都被称为默认构造函数,并且默认构造函数只能有一个。

主要注意的是:无参的构造函数、全缺省的构造函数、编译器生成的构造函数只能有一个,否则会有调用歧义。

譬如下图代码,编译器则会不知道调用的是哪个函数。

总结:不用传递参数就可以调用的构造函数就是默认构造函数。 

2.析构函数

2.1概念

刚刚我们学习了构造函数,现在我们已经知道一个对象是怎么来的了,那么它是怎么没的呢?这就需要析构函数来大显神威了!

析构函数:与构造函数功能相反,析构函数不是完成对对象的销毁,局部对象的销毁工作(生命周期)是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

2.2特性

析构函数是特殊的成员函数,其特征如下:

  • 析构函数名是在类名前加上~
  • 无参数无返回值类型
  • 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  • 析构函数不能重载
  • 对象生命周期结束时,C++编译系统自动调用析构函数。

下面我们还是来使用一下它

typedef int DataType;
class STack
{
public:STack(size_t capacity = 3){_a = (DataType*)malloc(sizeof(DataType) * capacity);if (!_a){perror("malloc fail!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_a[_size] = data;_size++;}~STack(){if (_a){cout << "我析构啦!" << endl;free(_a);_a = NULL;_capacity = 0;_size = 0;}}
private:DataType* _a;int _capacity;int _size;
};
int main()
{STack s;s.Push(1);
}

这里我们可以发现,当s的生命周期要结束时,编译器自动调用了析构函数。

  • 与构造函数类似,编译器生成的析构函数也只会调用自定义类型的析构函数
class Time
{
public:
~Time()
{
cout << "我析构啦!" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}

 这里不再画序号帮助大家理解过程,而是通过文字帮助大家深入理解原理
 在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?
原因:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month,
_day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是,main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁。main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析构函数。
注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数
 

  • 如果类中没有在堆上申请资源,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。。

3.拷贝构造函数

3.1概念

在现实生活中,我们在超市买小面包,可以认为同一种类型的两袋小面包是一样的。

那么,有没有一样的对象呢?我们能否创建一个跟已有对象一样的对象呢?

这就引入了我们的拷贝构造函数。

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),再用已存在的类类型对象创建新对象时由编译器自动调用。

3.2特性

  • 拷贝构造函数是构造函数的一个重载形式。
  • 拷贝构造函数的参数只有一个而且必须是类类型对象的引用,使用传值方式编译器会报错,因为会引发无穷递归调用。
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Date(const Date d) // 错误写法:编译报错,会引发无穷递归
Date(const Date& d) // 正确写法。
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
return 0;
}

  • 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造对象按照内存存储字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。(和memcpy的拷贝模式一样)。

对于我们的Date类来说,值拷贝就已经够用了,但是别的类呢?就譬如说我们的栈

typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

我们在运行这段代码时会发现它崩溃了,这是为什么呢?我们的s1对象中使用malloc动态开辟了一块内存,而我们是字节序拷贝的,因此我们的s2的array数组也指向了这块内存,而在程序退出时,s2和s1都要销毁,此时s2先销毁,s1再销毁(原因是栈区先进后出),s2已经将malloc的那块内存释放掉了,s1再去释放就会崩溃了。

 因此,我们可以得到如此一个结论:类中如果没有涉及到资源的申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数必须要写。

3.3拷贝构造的使用方法

我们的拷贝构造有两种写法,分别如下:

Stack s2(s1);//新创一个对象s2,并将s1拷贝给s2。
Stack s2 = s1;//这样也是可以完成拷贝的。

4.运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其
返回值类型函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

注意点:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
  • 藏的this
  • .*   ::   sizeof   ?:     .    注意以上5个运算符不能重载。

现在我们来重载一个运算符:

//类内-->成员函数
bool operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}
//类外-->全局函数
bool operator==(const Date& d1, const Date& d2)
{
return d1._year == d2._year
&& d1._month == d2._month
&& d1._day == d2._day;
}

在这里提一句题外话,我们在写代码的途中,能用引用返回或者引用传值时就尽量用引用,因为它它的效率会比较高。至于能否用引用返回,这需要我们关注他们的生命周期。 

5.赋值运算符重载

  • 参数类型:const Date&, 传递引用可以提高传参效率
  • 返回值类型 Date&,返回引用可以提高返回的效率,有返回值的目的是为了方便连续赋值
  • 检测是否自己给自己赋值
  • 返回*this,以满足连续赋值。
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//成员函数-->第一个参数是隐藏的this指针Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year;int _month;int _day;
};
//全局函数-->没有隐式的this,需要传递两个参数。
Date& operator=(const Date& Mythis,const Date& d)
{if (Mythis != &d){Mythis._year = d._year;Mythis._month = d._month;Mythis._day = d._day;}return *Mythis;
}

按理来说,上述的代码是可以跑的过去的,但是实际上会产生编译错误。

为什么赋值运算符必须是成员函数呢?

这是因为赋值运算符如果不显式实现,编译器会生成一个默认的赋值运算符,此时用户再在类外自己实现一个全局的赋值运算符重载就会和编译器在类内生成的默认赋值运算符重载冲突。因此运算符重载只能是类的成员函数

如果我们不显式实现赋值运算符的话,编译器生成的赋值运算符是以值的方式逐字节拷贝

注意:

  • 1.内置类型成员变量是直接赋值的,而自定义类型的成员变量需要调用对应的类的赋值运算符重载完成赋值。
  • 需要深拷贝的类需要我们手写赋值运算符,浅拷贝即可解决需求的类用默认生成的即可。

关于运算符重载的知识这里不再阐述,博主会在后续写一篇日期类的实现讲运算符重载更加深入的讲解。 

6.const修饰函数

如果我们想要用const修饰类内某个成员函数的this指针,应该如何实现呢?

CPP将const修饰的成员函数称为const成员函数,而const修饰类成员函数,实际上修饰的是该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

譬如这段代码

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};int main()
{const Date d2(2022, 1, 13);d2.Print();//errorreturn 0;
}

 由于我们传递的d2const的,但是在调用Print函数时,*this并没有加const修饰,这就造成了权限的放大,是不被允许的。因此我们应当将Print函数加上const修饰。

	void Print() const{cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}

7.取地址及const取地址操作符重载

取地址(&)也是可以重载的,不过一般情况下不需要我们写重载函数。

class Date
{
public:Date* operator&(){return this;}const Date* operator&()const{return this;}
private:int _year; // 年int _month; // 月int _day; // 日
};

二.struct和class的对比

1struct

1.1struct的成员

在C++中,struct中不仅可以放数据类型,而且可以放函数。这个函数可以在类内定义,也可以在类外定义。

  • 类内定义
#include <iostream>
using namespace std;
struct kuzi
{int Add(int a, int b){return a + b;}
};
int main()
{struct kuzi trousers;printf("%d", trousers.Add(3, 2));return 0;
}

  • 类外定义 

 1.1.2结构体的默认访问权限

在结构体中,为了兼容C语言,数据成员的默认访问权限为public,这也就代表着它们可以在结构体的外部直接进行访问。

如以下代码,我们可以直接给trousers这个对象的a和b进行赋值。

struct kuzi
{int a;int b;
};
int main()
{struct kuzi trousers;trousers.a = 3;trousers.b = 5;return 0;
}

 1.1.3访问权限控制

在C++11的标准中,引入了结构体成员的引用控制修饰符(public,privata,protect),我们可以显式的控制它的成员的访问权限。  

struct kuzi
{//默认是publicint a;int b;
private:int c;int d;
};

1.2.class

在C++中,类(class)是一种重要的概念,可以创建用户定义的数据类型,其中可以包括数据成员成员函数。而且,C++中的类支持继承和多态等面向对象的概念,允许你通过基类创建派生类,实现代码的扩展和重用。剩下的知识点已经讲解过了,这里不再赘述。

1.3结构体Struct和类Class之间的区别以及各自使用场景

C++中的结构体(struct)和类(class)有一些相似之处,但也存在一些关键的区别。以下是结构体和类之间的主要区别:

1、默认访问权限:

结构体的成员默认访问权限是公共(public),因此结构体的成员在外部可以直接访问。
类的成员默认访问权限是私有(private),因此类的成员在外部不能直接访问,需要通过公共的成员函数来访问。
2、成员函数:

类可以包含成员函数,这些函数可以操作类的私有成员,并且可以实现类的行为和功能。
结构体也可以有成员函数,但是它们的主要目的是为了实现一些操作,而不是类似于类的行为。
3、继承:

类可以通过继承实现子类与父类之间的关系,可以使用公共、保护或私有继承来控制成员的访问权限。
结构体也可以继承,但由于其成员默认是公共的,继承可能导致访问权限问题,当然我们也可以控制其访问权限,让其可以继承。
4、构造函数和析构函数:

拥有构造函数和析构函数,用于对象的初始化和清理。
结构体也可以有构造函数和析构函数(但不会默认生成),但是它们的使用场景通常是比较简单的数据封装。
5、默认成员访问标签(Access Labels):

在类和结构体中,可以使用访问标签(public、private、protected)来指定成员的访问权限。

6、 使用场景:

结构体的使用场景:

用于存储一组相关的数据,但没有复杂的操作和逻辑。
类的使用场景:

当你需要封装数据并附加操作和行为时,类更适合,因为它可以将数据和操作封装在一起。
在实现更复杂的数据结构,如树、图等,使用类也更加合适。
总结:
  虽然结构体和类在某些方面很相似,但它们的默认行为、访问权限、使用场景以及是否支持面向对象编程的特性(如继承、多态等)都有一些差异。在选择使用结构体还是类时,需要考虑你的代码的需求和设计目标。但是,结构体可以做的事类都可以干,结构体不可以干的事类也都可以干!

码字不易,如果你觉得博主写的不错,给个三联关注评论把!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【漯河市人才交流中心_登录安全分析报告-Ajax泄漏滑动距离导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

Windows10(家庭版)中DockerDesktop(docker)的配置、安装、修改镜像源、使用

场景 Windows10中Docker的安装与遇到的那些坑: Windows10中Docker的安装与遇到的那些坑_在 docker.core.logging.httpclientexceptionintercept-CSDN博客 上面讲Docker Desktop在windows10非家庭版上的安装&#xff0c;如果是家庭版&#xff0c;则需要执行如下步骤。 注&am…

【python】OpenCV—Tracking(10.2)

文章目录 BackgroundSubtractorcreateBackgroundSubtractorMOG2createBackgroundSubtractorKNN BackgroundSubtractor Opencv 有三种背景分割器 K-Nearest&#xff1a;KNN Mixture of Gaussian&#xff08;MOG2&#xff09; Geometric Multigid&#xff08;GMG&#xff09; …

K210视觉识别模块学习笔记4: 训练与使用自己的模型_识别字母

今日开始学习K210视觉识别模块: 模型训练与使用_识别字母 亚博智能的K210视觉识别模块...... 固件库: maixpy_v0.6.2_52_gb1a1c5c5d_minimum_with_ide_support.bin 文章提供测试代码讲解、完整代码贴出、测试效果图、测试工程下载 这里也算是正式开始进入到视觉识别的领域了…

matplotlib ---词云图

词云图是一种直观的方式来展示文本数据&#xff0c;可以体现出一个文本中词频的使用情况&#xff0c;有利于文本分析&#xff0c;通过词频可以抓住一篇文章的重点 本文通过处理一篇关于分析影响洋流流向的文章&#xff0c;分析影响洋流流向的主要因素都有哪些 文本在文末结尾 …

基于Freertos的工训机器人

一. 工训机器人 V1 1. 实物 将自制的F4开发板放置车底板下方&#xff0c;节省上方空间&#xff0c;且能保证布线方便整齐。 2. SW仿真 使用SolidWorks进行仿真&#xff0c;且绘制3D打印件。 工训仿真 3.3D打印爪测试 机械爪测试 二. 工训机器人 V2 1. 实物 工训机器人V2不同于…

IDEA 打开项目后看不到项目结构怎么办?

1、先把这个项目从 IDEA 中移除 2、再重新打开或导入 3、如果还没有解决&#xff0c;就先把这个项目拷贝出来把原来的路径上的项目给删除&#xff0c;然后再把拷贝后的项目放在一个路径下&#xff0c;再打开就可以了

沟通程序化(1):跟着鬼谷子学沟通—“飞箝”之术

沟通的基础需要倾听&#xff0c;但如果对方听不进你的话&#xff0c;即便你说的再有道理&#xff0c;对方也很难入心。让我们看看鬼谷子的“飞箝”之术能给我们带来什么样的启发吧&#xff01; “飞箝”之术&#xff0c;源自中国古代兵法家、纵横家鼻祖鬼谷子的智慧&#xff0…

​LabVIEW超声波检测

LabVIEW超声波检测 在现代工业生产和科学研究中&#xff0c;超声检测技术因其无损性、高效率和可靠性而被广泛应用于材料和结构的缺陷检测。然而&#xff0c;传统的超声检测仪器往往依赖于操作者的经验和技能&#xff0c;其检测过程不够智能化&#xff0c;且检测结果的解读具有…

Appium系列(2)元素定位工具appium-inspector

背景 如实现移动端自动化&#xff0c;依赖任何工具时&#xff0c;都需要针对于页面中的元素进行识别&#xff0c;通过识别到指定的元素&#xff0c;对元素进行事件操作。 识别元素的工具为appium官网提供的appium-inspector。 appium-inspector下载地址 我这里是mac电脑需要下…

使用Python突破网站验证码限制

之前有小伙伴说&#xff0c;在web自动化的过程中&#xff0c;经常会被登录的验证码给卡住&#xff0c;不知道如何去通过验证码的验证&#xff0c;今天专门给大家来聊聊验证码的问题。 常见的验证码一般分为两类&#xff0c;一类是图文验证码&#xff0c;一类是滑块验证码&#…

vue2+antv/x6实现er图

效果图 安装依赖 npm install antv/x6 --save 我目前的项目安装的版本是antv/x6 2.18.1 人狠话不多&#xff0c;直接上代码 <template><div class"er-graph-container"><!-- 画布容器 --><div ref"graphContainerRef" id"gr…

SpringCloud如何实现SSO单点登录?

目录 一、SpringCloud框架介绍 二、什么是SSO单点登录 三、单点登录的必要性 四、SpringCloud如何实现SSO单点登录 一、SpringCloud框架介绍 Spring Cloud是一个基于Spring Boot的微服务架构开发工具集&#xff0c;它整合了多种微服务解决方案&#xff0c;如服务发现、配置…

es的总结

es的collapse es的collapse只能针对一个字段聚合&#xff08;针对大数据量去重&#xff09;&#xff0c;如果以age为聚合字段&#xff0c;则会展示第一条数据&#xff0c;如果需要展示多个字段&#xff0c;需要创建新的字段&#xff0c;如下 POST testleh/_update_by_query {…

C#WPF数字大屏项目实战07--当日产量

1、第2列布局 第2列分三行&#xff0c;第一行分6列 2、当日产量布局 3、产量数据布局 运行效果 4、计划产量和完成度 运行效果 5、良品率布局 1、添加用户控件 2、用户控件绘制圆 2、使用用户控件 3、运行效果 4、注意点 这三个数值目前是静态的&#xff0c;可以由后台程序项…

构建高效稳定的短视频直播系统架构

随着短视频直播的迅猛发展&#xff0c;构建一个高效稳定的短视频直播系统架构成为了互联网企业的重要挑战。本文将探讨如何构建高效稳定的短视频直播系统架构&#xff0c;以提供优质的用户体验和满足日益增长的用户需求。 ### 1. 短视频直播系统的背景 短视频直播近年来蓬勃发…

ARM-V9 RME(Realm Management Extension)系统架构之系统安全能力的信任根服务

安全之安全(security)博客目录导读 目录 一、信任根服务 1、非易失性存储 2、根看门狗 3、随机数生成器 4、加密服务 5、硬件强制安全性 本节定义了系统架构必须支持的一般安全属性和能力&#xff0c;以确保RME安全性。 本章扩展了可能属于系统认证配置文件的一部分的其…

k8s之PV、PVC

文章目录 k8s之PV、PVC一、存储卷1、存储卷定义2、存储卷的作用2.1 数据持久化2.2 数据共享2.3 解耦2.4 灵活性 3、存储卷的分类3.1 emptyDir存储卷3.1.1 定义3.1.2 特点3.1.3 用途3.1.4 示例 3.2 hostPath存储卷3.2.1 定义3.2.2 特点3.2.3 用途3.2.4 示例 3.3 NFS存储卷3.3.1 …

SQL数据库多表创建之一对多、多对多表创建

MySQL多表创建关联及操作_mysql创建关联表-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞21次&#xff0c;收藏20次。表与表之间的关系表语表之间的关系&#xff0c;说的就是表与表数据之间的关系。_mysql创建关联表https://blog.csdn.net/2401_83641392/article/details/137031…

【计算机毕业设计】345大学生心理健康测评管理系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…