当前位置: 首页 > news >正文

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

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

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、 使用场景:

结构体的使用场景:

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

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

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

相关文章:

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

一.类中生成的默认成员函数详解 0.类的6个默认成员函数 编译器会给类生成六个默认成员函数&#xff0c;在类中即使我们什么都不做&#xff0c;也会自动生成。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。 下面我们逐…...

C语言与内存息息相关的重要概念有哪些?

一、问题 C语⾔、C语⾔和C#语⾔&#xff0c;这三门语⾔&#xff0c;⼀个⽐⼀个加号&#xff08;&#xff09;多&#xff0c;C语⾔没有加号&#xff0c;C有两个加号&#xff0c;C#有四个加号。随着语⾔的发展&#xff0c;⼀个⽐⼀个简单&#xff0c;很多问题系统都给做了&#x…...

【chagpt】广泛使用API之前:考虑成本和数据隐私

文章目录 一. 定价和标记限制二. 安全和隐私 在广泛使用API之前&#xff0c;应该考虑两个重要因素&#xff1a;成本和数据隐私。 一. 定价和标记限制 OpenAI在Pricing页面上列出了模型的定价。请注意&#xff0c;OpenAI不一定及时更新该页面上的定价信息&#xff0c;因此实际…...

六月后考研如何备考看这一篇就够了

以下是考研六月后可以参考的规划&#xff1a; 6 月至 8 月&#xff08;强化阶段&#xff09;&#xff1a; 英语&#xff1a;继续背单词&#xff0c;开始刷历年真题中的阅读部分&#xff0c;仔细分析错题原因&#xff0c;总结解题技巧。数学&#xff1a;完成基础阶段的复习后&am…...

Linux主机连接腾讯云服务器详细配置

硬件条件 当然你要先有一个云服务器&#xff0c;腾讯云比阿里云便宜一点&#xff0c;所以就用腾讯云了 问了师兄买这个98的就行&#xff0c;选择CentOS&#xff0c;不要选Ubuntu&#xff0c;因为 嗯&#xff0c;大概就是这样 编程测试 云服务器当然是作为服务端 server.cpp…...

数字化工厂怎么收集,处理数据?

数字化工厂的数据收集与处理 数字化工厂是现代化工厂&#xff0c;利用数字技术和数据分析提高效率和优化流程。数据分析作为数字化工厂的核心技术&#xff0c;对数据的获取与处理至关重要。在数字化工厂中&#xff0c;数据的来源包括企业内部信息系统、物联网信息以及外部信息&…...

OOM不会导致JVM退出

问题来源 一次生产事故&#xff0c;由于一次性从数据库查询过多数据导致线程 OOM&#xff1a;Java heap space 异常&#xff08;千万级表&#xff0c;JVM堆内存2G&#xff09;&#xff0c;但是在线程OOM发生时&#xff0c;java进程却没有立即挂掉。 ##OOM与异常 说到底OutOfM…...

C++学习日记 | LAB 6 static library 静态库

资料来源&#xff1a;南科大 余仕琪 C/C Program Design LINK&#xff1a;CPP/week06 at main ShiqiYu/CPP GitHub 一、本节内容 本节主要介绍静态库和动态库。 1.1 静态库和动态库的概念 静态链接和静态库(也称为存档)是链接器将所有使用的库函数复制到可执行文件的结果。静…...

他用AI,抄袭了我的AI作品

《大话西游》里面有一句经典台词&#xff1a;每个人都有一个妈&#xff0c;但是“你妈就一定是你妈吗&#xff1f;” 用AI创作的艺术作品&#xff0c;也走进类似的困境&#xff1a;如何证明你用AI生成的作品&#xff0c;就是你的作品&#xff1f; 近日&#xff0c;腾讯科技独…...

力扣刷题--2956. 找到两个数组中的公共元素【简单】

题目描述 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;它们分别含有 n 和 m 个元素。 请你计算以下两个数值&#xff1a; 统计 0 < i < n 中的下标 i &#xff0c;满足 nums1[i] 在 nums2 中 至少 出现了一次。 统计 0 < i < m 中的下标 i &am…...

海信集团携纷享销客启动LTC数字化落地 推动ToB业务再升级

日前&#xff0c;海信集团携手连接型CRM纷享销客正式启动LTC&#xff08;Leads to Cash&#xff09;数字化平台实施落地项目。作为海信集团数字化的重要里程碑&#xff0c;该项目将通过统一规划、统一投资、统一平台、资源共享和数据赋能&#xff0c;构建ToB业务数字化经营管理…...

【Go语言入门学习笔记】Part5.函数

一、前言 这里的还是跟C有区别的&#xff0c;大家熟悉了其他语言后&#xff0c;还得注意一下这里的内容。Go的函数非常灵活。 二、学习代码 package mainimport "fmt"// ZhengXing 类似typedef的方法 type ZhengXing int// 函数名有说法&#xff0c;首字母大写是pu…...

磁珠笔记汇总

磁珠笔记汇总 磁珠是和电感很相似的器件。 电感磁珠单位亨(H)欧姆(Ω)是否储能存储能量消耗高频能量应用场景通常用于开关电源吸收高频&#xff0c;EMC保护如何看待损耗使用电感时希望损耗越小越好使用磁珠时是利用其损耗来消耗不需要的高频分量 一、磁珠的工作原理 磁珠与…...

【css3】02-css3新特性之选择器篇

目录 1 属性选择器 2 结构伪类选择器 3 其他选择器 :target和::selection ::first-line和::first-letter 4 伪类和伪元素的区别 伪类&#xff08;Pseudo-classes&#xff09; 伪元素&#xff08;Pseudo-elements&#xff09; 伪类和伪元素的区别 1 属性选择器 ☞ 属性选…...

修正错误的插入排序

错误版 void InsertSort(vector<int>& nums) {for (int i 0; i < nums.size()-1; i){int end i;int t nums[end 1];while (end > 0){if (nums[end1] < nums[end]) nums[end 1] nums[end];else break;--end;}nums[end 1] t;} } 无法得到正确结果。…...

Unity 权限 之 Android 【权限 动态申请】功能的简单封装

Unity 权限 之 Android 【权限 动态申请】功能的简单封装 目录 Unity 权限 之 Android 【权限 动态申请】功能的简单封装 一、简单介绍 二、Android 权限 动态申请 三、实现原理 四、注意事项 五、案例实现简单步骤 附录&#xff1a; 一、进一步优化 二、多个权限申请…...

跟进2年弄丢1.8亿,你的大客管理错在哪里?

数量并非目的之所在&#xff0c;质量才是根本之道。重视1%的超级用户&#xff0c;才是提高效率的关键所在。 ——凯文凯利 在当今的商业环境中&#xff0c;大客户已成为销售服务型企业最宝贵的资产。他们不仅贡献了企业收入的重要一环&#xff0c;…...

浅说线性DP(上)

前言 在说线性dp之前&#xff0c;我们先来聊一聊动态规划是啥&#xff1f; 动态规划到底是啥&#xff1f; 动态规划是普及组内容中最难的一个部分&#xff0c;也是每年几乎必考的内容。它对思维的要求极高&#xff0c;它和图论、数据结构不同的地方在于它没有一个标准的数学…...

leetcode题目18

四数之和 中等 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#xf…...

后端企业级开发之yaml数据序列化格式文件详解2024

yaml格式 数据格式 yaml 是一种数据序列化的格式 容易阅读 容易与脚本语言交互 以数据为核心 重数据轻格式 我们要知道他怎么书写 大小写敏感 属性层级关系使用多行描述 每行结尾使用冒号结束 使用缩进表示层级关系 同层级左侧对其 只运行使用空格 属性前面添加空格 #表…...

智能界面设计:数字孪生与大数据结合的美学典范

智能界面设计&#xff1a;数字孪生与大数据结合的美学典范 引言 在数字化浪潮的推动下&#xff0c;智能界面设计成为了连接用户与技术的重要桥梁。数字孪生技术与大数据的结合&#xff0c;不仅为UI设计带来了前所未有的创新机遇&#xff0c;更成为了美学与功能性融合的典范。…...

听说部门来了个00后测试开发,一顿操作给我整麻了

公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司实习半年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍&#xff01…...

Linux shell命令

cat 文件名 查看文件内容&#xff0c; tac文件名 倒着显示。 more 文件名 显示内容 less文件名 和more的功能一样&#xff0c;按上下左右键&#xff0c;按Q键结束。 head文件名&#xff0c;只显示前10行内容。 ln是一个默认创建硬链接的命令 ln 文件名 ls -i文件名…...

【Linux】Linux基本指令1

1.软件&#xff0c;OS&#xff0c;驱动 我们看看计算机的结构层次 1.1.操作系统 操作系统是一款做 软硬件管理 的软件 操作系统&#xff08;计算机管理控制程序&#xff09;_百度百科 (baidu.com) 操作系统&#xff08;英语&#xff1a;Operating System&#xff0c;缩写&a…...

重学java 49 增强for

知之俞明&#xff0c;则行之越笃&#xff1b;行之愈笃&#xff0c;则知之愈益&#xff1b; —— 24.5.28 一、基本使用 1.作用: 遍历集合或者数组 2.格式: for(元素类型 变量名:要遍历的集合名或者数组名) 变量名就是代表的每一个元素 3.快捷键: 集合名或者数组名.for package …...

BUUCTF靶场[Web] [极客大挑战 2019]Havefun1、[HCTF 2018]WarmUp1、[ACTF2020 新生赛]Include

[web][极客大挑战 2019]Havefun1 考点&#xff1a;前端、GET传参 点开网址&#xff0c;发现是这个界面 点击界面没有回显&#xff0c;老规矩查看源代码&#xff0c;看到以下代码 代码主要意思为&#xff1a; 用get传参&#xff0c;将所传的参数给cat&#xff0c;如果catdog…...

现代信号处理11_Spectral Analysis谱分析(CSDN_20240526)

谱分析与傅里叶变换 对于一个信号&#xff0c;一方面可以从时域上对其进行分析&#xff0c;另一方面也可以从频域上对其进行认识&#xff0c;对信号进行频谱分析能够帮助我们了解能量在频域上的分布。 确定性信号的能量通常是有限的&#xff0c;而平稳随机信号的能量通常是无限…...

C#开发上位机应用:基础与实践

C#是一种流行的面向对象编程语言&#xff0c;常用于Windows应用程序的开发。上位机应用是一种用于监控和控制设备或系统的应用程序&#xff0c;通常与下位机&#xff08;如传感器、执行器等&#xff09;进行通信。在本文中&#xff0c;我们将介绍C#开发上位机应用的基础知识和实…...

话术巧妙分隔沟通效果更佳看看这个小技巧

客服回复客户咨询&#xff0c;如果遇到比较复杂的问题&#xff0c;经常会有大段的文字回复&#xff0c;用聊天宝的分段符功能&#xff0c;在需要分段的地方点击右上角的“插入分隔符”&#xff0c;就可以在指定位置分段&#xff0c;实现多段发送的目的。 前言 客服回复客户咨询…...

【Spring】设计模式(GOF)

Spring Framework在其架构和实现中广泛使用了多种GOF&#xff08;Gang of Four&#xff09;设计模式。这些设计模式帮助Spring解决了许多常见的软件开发问题&#xff0c;提高了代码的可重用性、可维护性和可扩展性。 1、工厂模式&#xff08;Factory Pattern&#xff09; 1.1简…...