C++类和对象万字详解(典藏版)

news2024/11/24 9:41:27

在这里插入图片描述

文章目录

  • 前言
  • 认识类和对象
    • 使用 struct 定义类
    • class 定义类
    • 类的声明和定义分离
    • 类大小的计算
    • this指针
      • this指针的常见的面试题
  • 构造函数与构析函数
    • 构造函数
      • 初始化列表
    • 构析函数
    • 默认生成的构造函数和构析函数
  • 拷贝构造函数
    • 默认类型转化与 explicit 关键字
  • static 成员变量
  • 运算符重载
  • 友元
    • 友元函数
    • 友元类
  • 内部类
  • 匿名对象

大家好,我是纪宁。
类和对象是C++编程中非常重要的概念,在生活中我们要经常使用类和对象来解决问题,掌握类和对象的使用方法对于编写高质量、高效率的C++代码至关重要。这篇文章将讲解类和对象相关的内容。

前言

首先C++是兼容C的,所以 C 的语法在 C++中 99%都可以使用,但根据一些C++大佬的说法是:“学了C++之后就不想再使用C了”,到底是怎么回事呢?

在C中,如果我们要定义一个可以描述事物的集合是,通常会定义一个结构体的复杂类型,里面可以存放多种描述这个事物特征的成员变量。但是,如果我们想表示这个事物可以具体进行那些操作的时候,还要另外设置函数,并将这个结构体类型作为参数传递进去,对这个函数进行封装,形成一个个‘方法’(成员函数)。在需要使用这个事物的某些操作的时候,只需要调用这些方法即可。
但是!众所周知,C++是对C的改进和提升,C++中定义了一种新的编程方式:面向对象编程的,在一个类中,可以将数据与操作数据的方法封装在一起,描述一类对象的属性和行为,形成一个或多个对象,从而实现程序的可重用性、可扩展性。

认识类和对象

使用 struct 定义类

在C中,struct 用来定义结构体,而在C++中,struct 也可以用来定义类

定义一个汽车类 Car

struct Car
{
	double price;
	int year;
};

这个类中包含了一辆汽车的基本信息,现在可以尝试通过这个汽车类定义一个对象 car,并打印它的基本信息。

int main()
{
	Car car;
	car.year = 1997;
	car.price = 134567.896;
	cout << car.year << endl;
	cout << car.price << endl;
	return 0;
}

但是,一个汽车肯定不只有属性,还有各种功能,如果我们想调用这些功能应该如何做呢?答案是向类中添加成员函数,这种函数被称为类的成员函数或者类的方法。我们可以尝试在汽车这个类添加一些汽车的方法或功能并调用这些方法。

添加汽车启动、行驶、熄火

struct Car
{
	double price;
	int year;
	void Startup()
	{
		cout << "汽车,启动!!!" << endl;
	}
	void Drive()
	{
		cout << "汽车行走了50km,用了半小时" << endl;
	}
	void Brake()
	{
		cout << "汽车在你一直踩刹车中停止!" << endl;
	}

};

int main()
{
	Car car;
	car.Startup();
	car.Drive();
	car.Brake();
	return 0;
}

运行结果:
在这里插入图片描述
现在,我们可以继续在Car这个类中添加其他的方法,但在此之前,要先补充一下基础知识。

class 定义类

要说到再C++中使用类,大家应该再熟悉不过的就是 class 了,它在定义类的基础语法上和 struct 是相同的。

class Car
{
	double price;
	int year;
	void Startup()
	{
		cout << "汽车,启动!!!" << endl;
	}
	void Drive()
	{
		cout << "汽车行走了50km,用了半小时" << endl;
	}
	void Brake()
	{
		cout << "汽车在你一直踩刹车中停止!" << endl;
	}
};

但是在调用的时候,编译器却报错了。
在这里插入图片描述
原因是在 class 定义的类中,里面的成员默认是私有的,只有在类内部才可以使用;而struct 定义的类里面的成员默认是公开的,在类内外都可以使用。所以在 class 定义的类中要加入访问限定符

  • public 公有
  • protected 保护
  • private 私有

那么,经过访问限定符修饰后的类就变成了:

class Car
{
	public:
		void Startup()
		{
			cout << "汽车,启动!!!" << endl;
		}
		void Drive()
		{
			cout << "汽车行走了50km,用了半小时" << endl;
		}
		void Brake()
		{
			cout << "汽车在你一直踩刹车中停止!" << endl;
		}
	private:
		double price;
		int year;
};

一般会将事物的基本属性放在私有里面,然后将事物的一些方法和功能函数放在公有里面。

类的声明和定义分离

如果要将类的声明放在.h文件中,可以使用如下的方法

class Car
{
public:
	void Startup();
	void Drive();
	void Brake();
	bool Promote()
	{
		return 0;
	}
private:
	double price;
	int year;
};

较长的函数,可以将它的声明放在.h文件中,较短的函数直接将函数定义放在类里。
声明后的.cpp文件中只需要写类的成员函数的定义部分就可以了。但是要在函数名前加 类名::,如下

void Car::Startup()
{
	cout << "汽车,启动!!!" << endl;
}
void Car::Drive()
{
	cout << "汽车行走了50km,用了半小时" << endl;
}
void Car::Brake()
{
	cout << "汽车在你一直踩刹车中停止!" << endl;
}

在这里插入图片描述这样,就可以在 .cpp文件中正常调用类的成员函数了。

类大小的计算

关于类的大小,计算规则有点类似于结构体的内存对齐,这里需要注意的一点是:类大小只计算成员变量大小(需要考虑内存对齐),而成员函数其实是储存在公共代码区的。

变量的声明和定义的区别:是否开了空间

一个类中,如果没有成员变量,它定义的对象大小并不是0而是1。这种类在定义对象的时候会开一个字节的空间,但这个字节不存储有效数据,作用是 标识定义的对象存在过。

this指针

如图,当d1调用成员函数 Print 的时候,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
在这里插入图片描述
其实,C++编译器在每个成员函数里定义了一个指针 this 作为成员函数的第一个形参,同时将调用此函数的对象地址作为参数传过去,默认在成员函数中访问成员变量就是对这个 this 指针指向对象里的成员变量进行访问。

this指针不能显式的写出this 相关的实参和形参,但在类中可以显式的使用 this 指针。如图:
在这里插入图片描述

this指针的常见的面试题

this 指针存在哪里?

前面已经学习过类的大小是由类中成员变量决定的,所以this指针肯定不是存储在类中。this指针是成员函数中定义的形参,与局部变量一样,一般存在函数栈帧上。但不同的编译器会对存储位置稍有优化,因为this指针会经常使用到,所以vs将this指针存储在 eax 这个寄存器中方便快速调用。

构造函数与构析函数

曾经,我们在定义栈,列表等这种复杂结构的时候,每次定义对应变量或对象后都要及时进行初始化,在即将要出作用域的时候要进行销毁。但粗心的我们经常会忘记调用初始化函数和销毁函数,但是有了C++后就可以利用构造函数和析构函数解决这一问题了。

构造函数

构造函数的定义写在类里面,用于初始化这个类创建的对象,构造函数有如下特征:

  • 函数名与类名称相同
  • 无返回值(void 都不用写)
  • 对象实例化时编译器自动调用对应的构造函数
  • 支持重载

如图,对日期类定义构造函数(全缺省非常合适)
声明
在这里插入图片描述
定义
在这里插入图片描述

那么,定义日期类的实例化对象的时候既可以使用如下方法:

Date d1;
Date d2(2023, 10, 24);
Date d3(2023);

当不传递参数的时候(也不需要带括号),默认实例化对象成员变量全部初始化为1;当正常传参的时候,就将实例化对象初始化为需要的值;当参数‘不足’时,就利用函数缺省的规则,优先对前面的形参进行传值。

初始化列表

初始化列表格式:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
在这里插入图片描述
相当于如下正常的构造函数
在这里插入图片描述
那为什么要使用初始化列表呢?

有的成员变量只能初始化一次,如const 限制的变量引用定义的成员变量无默认构造函数的自定义类型成员等,所以只能使用初始化列表来初始化。
在这里插入图片描述
但需要注意一点:引用定义的成员变量在使用初始化列表进行初始化的时候,不能使用形参来给引用赋值,否则在构造函数结束后,引用的成员变量就会变为随机值。
初始化列表的顺序
成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。所以为了避免出现歧义,建议声明顺序和初始化列表顺序保持一致。

初始化列表和函数体内初始化可以配合使用

如下面的例子:
在这里插入图片描述
在这里插入图片描述
初始化列表的时候会将所有成员全部定义,如果在初始化列表的时候没有显示写某些成员,编译器也会定义,只不过内置类型会被初始化为随机值,而自定义类型则会去调用它自己的默认构造函数。定义时就要初始化的变量必须显示写出来。

构析函数

定义方法:在类名前面加~,无参,无返回值。写在类中,在对象生命周期结束时自动调用,用来释放动态内存申请的资源。
如栈的构析函数:

~Stack()
{
	if (_array)
	{
		free(_array);
		_array = NULL;
		_capacity = 0;
		_size = 0;
	}
}

默认生成的构造函数和构析函数

不写构造函数和构析函数的情况下,编译器会生成默认的构造函数和析构函数。系统默认生成的,对此对象内置类型的成员变量不做处理,自定义类型的成员变量自动调用它的构造函数和析构函数(其实就是一种辅助,将写好的,能用的调用过来)。如果写了对应的构造函数和析构函数,编译器会优先调用。
对于内置类型不自动初始化的漏洞,C++11在原有基础上打了一个补丁,即:允许在声明成员变量的时候给初始值。
在这里插入图片描述
这样,即使内置类型没有在构造函数里自动初始化,也不影响它有初始值。

拷贝构造函数

在C语言中,有时会使用浅拷贝,如在结构体传参的时候不传指针,直接将结构体传过去,这种直接传值,形参进行拷贝的情况叫浅拷贝(也叫值拷贝),即将变量的值原封不动的复制一份。

但是,这种浅拷贝在C++中是有风险的,当在C++中拷贝对象的时候,如果实例化对象中申请了动态的空间,按值拷贝的话会导致指针指向同一块空间,而C++中有析构函数,在对象声生命周期结束时会自动调用,则这块空间会被释放两次,第二次释放的时候就产生的野指针和越界访问的问题。

编译器自己其实也生成了默认的拷贝构造函数,这个默认生成的拷贝构造函数是按值拷贝的,如果未涉及到内存申请,那么这样的值拷贝是可行的,但如果涉及到了内存申请,那么值拷贝就对导致同一块空间被释放两次,最终导致程序崩溃。

拷贝构造是函数构造的一种重载,那么它的形式和函数构造的差不多的,唯一需要注意的是,形参必须用引用来定义。如果不传引用,自定义类型传参的时候就会引发无穷递归:拷贝的时候要调用拷贝构造函数,拷贝构造函数传参的时候又要进行拷贝…无穷尽了。

拷贝构造函数通常为了规避写错,会在形参定义前加 const

如下面的代码:

Date::Date(const Date& dd)
{
	_year = dd._year;
	_month = dd._month;
	_day = dd._day;
}
Stack(Stack&st)
{
	_a = (int*)malloc(sizeof(int) * st.capacity);
	if (_a == nullptr)
	{
		perror("malloc fail");
		exit(-1);
	}
	memcpy(_a, st._a, sizeof(int) * st._top);
	_top = st._top;
	_capacity = st._capacity;
}

就用上面的日期类来举例子看拷贝构造的内部原理:
在这里插入图片描述
在这里插入图片描述

将d2拷贝给d3,调用拷贝构造函数,如上图,dd是d2的别名,而拷贝构造函数内部的this指针是指向d3的,即将对象d2成员变量的值依次赋值给d3。

默认类型转化与 explicit 关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
先解释一个点:默认不同类型再进行赋值的时候,都要进行隐式类型转化(前提是能转化),转化的过程是先创建一个临时变量来存储转化后的,然后再进行同类型变量之间的赋值。
内置类型对象也可以转化为自定义类型的对象,能支持这个转换,是有自定义对象有带缺省值的构造函数(自己定义的构造函数)。
用内置类型直接给对象赋值/初始化的时候,实际编译器背后会用这个内置类型通过带缺省值默认构造函数构造一个无名对象,最后用无名对象给d1对象进行赋值。
在这里插入图片描述
但是说实话这种代码的可读性不是非常好,为了防止这种情况的出现,我们可以使用explicit关键字来对构造函数进行修饰,explicit修饰过的构造函数,禁止类型转换
在这里插入图片描述
再次进行上面情况的赋值时,编译器就会报错:
在这里插入图片描述

static 成员变量

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用 static 修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。

静态成员变量
在这里插入图片描述

静态成员函数
在这里插入图片描述
使用样例
在这里插入图片描述

类的静态成员的特性

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

面试题目 static 的应用举例

面试题:实现一个类,计算程序中创建出了多少个类对象。

class A
{
public:
	A() 
	{
		++_scount;
	}
	A(const A& t) 
	{
		++_scount; 
	}
	~A() 
	{
		--_scount; 
	}
	static int GetACount() 
	{
		return _scount; 
	}
private:
	static int _scount;
};
int A::_scount = 0;

void TestA()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
}

int main()
{
	TestA();
}

程序解释:在类的私有部分定义一个静态成员变量,每个类都共享这个成员变量。在类外对静态成员变量定义并初始化为0,每调用一次构造函数和构造拷贝函数说明就多创建了一个对象,就对静态成员变量的值加1,等到最后程序即将结束的时候再利用 类:: 成员 来访问成员函数得到它的成员变量的值。这个成员变量的值就是程序中创建对象的个数。

运算符重载

内置类型使用运算符的时候,编译器会将它转化为指令,自定义类型却不可以直接使用运算符。C++中的运算符重载可以让自定义类型可以直接使用运算符。
使用方法:在使用的时候还是正常使用运算符,但需要在类中使用 operator关键字提前定义好对应的运算符重载函数。
如下面的日期类的+=运算符重载(定义与声明分离)

int Date::GetMonth(int year,int month)
{
	int Month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
	{
		return 29;
	}
	else
	{
		return Month[month];
	}
}
Date& Date::operator+=(int x)
{
	_day+= x;
	while (_day > GetMonth(_year, _month))
	{
		_day -= GetMonth(_year, _month);
		_month++;
		if (_month == 13)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

日期类的 >运算符重载代码(<直接对这个进行逻辑取反)

bool Date::operator>(const Date&d)
{
	if (_year > d._year)
	{
		return true;
	}
	if (_year == d._year && _month > d._month)
	{
		return true;
	}
	if (_year == d._year && _month > d._month && _day > d._day)
	{
		return true;
	}
	return false;
}

日期类的==运算符重载代码

bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

日期类-=运算符重载

Date& Date::operator-= (int x)
{
	if (x < 0)
	{
		*this += -x;
	}
	else
	{
		_day -= x;
		while (_day <= 0)
		{
			_month--;
			if (_month == 0)
			{
				_year--;
				_month = 12;
			}
			_day += GetMonth(_year, _month);
		}
	}
	return *this;
}

日期类-运算符重载(两个日期相减)


int Date::operator-(const Date& d)
{
	int flag = 1;
	Date max = *this;
	Date min = d;
	int count = 0;
	if (max < min)
	{
		max = d;
		min = *this;
		flag = -1;
	}
	while (min != max)
	{
		count++;
		min++;
	}
	return count * flag;
}

通俗的来讲,就是对 this 指针指向的对象的成员进行操作,使其在某种意义上根据使用者的意愿达到使用运算符进行计算的程度。
需要注意的点:运算符需要什么样的返回类型,运算符重载时就要使用什么样的返回值;比较函数需要放在类里。
是否使用引用返回?
出了作用域还未销毁的,就可以使用引用返回,如this指针(在+=,-=等的重载直接对this指针操作时可以使用引用返回);当在+、- 等需要先拷贝this指针内容的情况下,不能用引用返回,因为这些拷贝的对象出作用域后会被销毁。

友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

代码耦合度
代码耦合度是指代码中的模块与模块之间的相互依赖程度。当模块之间相互依赖度高时,就会导致代码的耦合度高,这会增加代码的复杂度,阻碍代码的维护和扩展。

友元分为:友元函数和友元类

友元函数

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

如要对 << 和 >> 进行运算符重载

在类里进行友元声明
在这里插入图片描述
此函数在类外也可访问这个类的私有
在这里插入图片描述
代码详解

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1, int month = 1, int day = 1)//构造函数
		:_year(year)
		, _month(month)
		, _day(day)
		, def(_year)
		, zop(month)
	{}
	~Date(){
		_year = _month = _day = 1;
	}
	Date(const Date& d)
		:zop(d.zop)
		, def(d.def){
		cout << d.def << "d2.def" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	void Print(){
		cout << _year << '/' << _month << '/' << _day << endl;
		cout << _year << '/' << _month << '/' << _day << endl;
		cout << def << '/' << zop << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	int& def;
	const int zop;
};

ostream& operator<<(ostream& _cout,const Date&d){
	cout << d._year << "/" << d._month << "/" << d._day << endl;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d){
	cin >> d._year;
	cin >> d._month;
	cin >> d._day;
	return _cin;
}
int main()
{
	Date d1;
	cout << d1;
	Date d2(2023, 11, 1);
	cout << d2;
	Date d3;
	cin >> d3;
	cout << d3;
	return 0;
}

友元类

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

友元类有以下特性:

  • 友元关系是单向的,不具有交换性。

比如在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

  • 友元关系不能传递
    如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  • 友元关系不能继承

内部类

内部类是指在类内定义的类,也被称为嵌套类。内部类可以访问外部类的所有成员,包括私有成员。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

内部类可以帮助我们更好的封装类的实现细节,同时也可以在外部类的成员函数中方便地使用内部类,从而减少代码的复杂度。

注意点

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

内部类举例

class Dog
{
private:
	static int k;
	int h;
public:
	//定义Goddess类,是Dog的内部类
	class Goddess // Goddess天生就是Dog的友元
	{
	public:
		void foo(const Dog& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int Dog::k = 1;
int main()
{
	Dog::Goddess b;
	b.foo(Dog());
	return 0;
}

代码解读:Goddess就是一个普通类,只是受Dog的类域和访问限定符的限制。Goddess天生是Dog的友元类,可以访问Dog的私有;但Gog却不是Goddess的友元类,Dog不能访问Goddess的任何私有!

匿名对象

在C++中,我们可以创建匿名对象。所谓匿名对象是指创建一个没有名字的临时对象。这种对象可以直接在函数调用或表达式中使用,而不需要定义变量名。

语法:类名()
如图,Date 是一个类
在这里插入图片描述
它的声明周期只有这一行,有时候需要对象来访问成员的时候用一个匿名对象就很好用。

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

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

相关文章

判断字符串是否为json

//营业时间返回数组String businessDate merchantInfoResp.getBusinessDate();Object obj JSON.parse(businessDate);if (obj instanceof JSONArray) {merchantInfoResp.setBusinessDateDesc(JSON.parseArray(JSON.toJSONString(obj), Integer.class));} else {//营业日期判断…

YB2408CAX系列是一款高效、高频的同步降压DC-DC转换器,最高可带载2A连续电流。

概述: YB2408CAX系列是一款高效、高频的同步降压DC-DC转换器&#xff0c;最高可带载2A连续电流。YB2408CAX系列可在2.7V到5.5V的宽输入电源电压下工作。内部的主开关和同步开关管的RoSO非常小&#xff0c;从而传导损耗很小&#xff0c;效率很高。该款芯片工作开关频率为1.5MHz…

向中学生郑重推荐电视剧《狂花凋落》

笔者为什么要向网友&#xff0c;特别是要向中学生网友&#xff0c;郑重推荐能真实反应当年“文革”时期知识青年上山下乡悲惨遭遇的电视剧《狂花凋落》&#xff0c;因为如果真的再来上一次那种亘古未有的人间浩劫&#xff0c;那么在蜜糖里泡大、丁点儿苦都吃不下的当今中学生&a…

操作系统备考学习 day12 (第五章)

操作系统备考学习 day12 第五章 &#xff08;输入/输出&#xff09;I/O管理5.1 I/O管理概述5.1.1 I/O设备I/O设备的分类 5.1.2 I/O控制器I/O设备的电子部件 5.1.3 I/O控制方式程序直接控制方式中断驱动方式DMA方式DMA控制器通道控制方式 5.1.4 I/O软件层次结构用户层软件设备独…

直播电商大变局:店播时代终于来了!

店播时代终于来了。 直播在2023年双十一的亮点&#xff0c;也是焦点。今年双十一&#xff0c;舆论场的注意力都集中在了几大平台的头部主播身上&#xff0c;却少有人注意店播的表现——根据淘宝直播官方数据&#xff0c;10月31日淘宝直播上有29个直播间开局即破亿&#xff0c;…

Pytorch从零开始实战08

Pytorch从零开始实战——YOLOv5-C3模块实现 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——YOLOv5-C3模块实现环境准备数据集模型选择开始训练可视化模型预测总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c…

应用层中一些零碎且易忘的知识点

邮件发送协议&#xff1a; SMTP&#xff1a;SMTP协议只能传送ASCII码文本数据&#xff0c;不能传送可执行文件或其他的二进制对象&#xff08;如带有图片、音频或视频数据的多媒体邮件&#xff09;MIMP&#xff1a;为解决SMTP传送非ASCII码文本的问题&#xff0c;提出了多用途因…

HR模块开发(1):简单的开发流程和注意事项

HR模块开发 一、模块概述 人力资源管理解决方案关注3个领域:每位雇员都发展和维护着‘公司内’和‘公司外’的种种‘关系’。运用科技,强化这些关系,可以提高忠诚度和生产力,公司整体得到商业价值。 员工关系管理员工职业生命周期管理员工事务处理管理HR模块的基本知识和构…

Linux: MV指令(覆盖替换重命名)

MV指令 mv [-bfiuv] [–help] [–version] [-S <附加字尾>] [-V <方法>] [源文件或目录] [目标文件或目录]-b 若需覆盖文件&#xff0c;则覆盖前先行备份-f 若目标文件或目录与现有的文件或目录重复&#xff0c;则直接覆盖现有的文件或目录-i 覆盖前先行询问用户–…

Python武器库开发-常用模块之copy模块(十五)

常用模块之copy模块(十五) 在Python编程中&#xff0c;我们经常遇到需要复制或拷贝数据的情况。为了避免不必要的问题和错误&#xff0c;Python提供了copy模块来处理复制操作。本文将介绍copy模块的用法&#xff0c;包括浅拷贝和深拷贝的概念以及如何在不同场景中使用。 我们…

【有源码】基于Python的篮球人才管理系统Springboot的篮球竞赛管理系统(源码、调试、lw、开题报告、ppt)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

算法题:16. 最接近的三数之和(Python Java 详解)

解题思路 Step1&#xff1a;先对数组排序&#xff0c;然后设置3个指针&#xff0c;指针1遍历范围为&#xff08;0~数组长度减2&#xff09;。 Step2&#xff1a;指针1位置确定时&#xff0c;指针1后面的数组元素首位各放置一个指针&#xff08;指针2、指针3&#xff09;。 S…

006 Linux 进程的概念 | 获取进程的PID

前言 本文将会向您进程的概念&#xff0c;程序与进程的区别&#xff0c;如何获取进程的标识符-pid 文章重点 1.描述进程——PCB 进程与程序的区别 CPU对进程列表的处理 2.获取进程PID 描述进程-PCB 进程概念 课本概念&#xff1a;程序的一个执行实例或正在执行的程序 内核…

在Flask中实现文件上传七牛云中并下载

在Flask中实现文件上传和七牛云集成 文件上传是Web应用中常见的功能之一&#xff0c;而七牛云则提供了强大的云存储服务&#xff0c;使得文件存储和管理变得更加便捷。在本篇博客中&#xff0c;我们将学习如何在Flask应用中实现文件上传&#xff0c;并将上传的文件保存到七牛云…

Java NIO 编程

1. 简介 Java NIO 是 JDK 1.4 中引入的新的 IO 方式&#xff0c;它主要包含 Buffer、Channel、Selector 这三个核心的组件&#xff0c;它与传统 IO 的区别如下&#xff1a; NIO IO 面向缓冲 面向流 同步非阻塞 同步阻塞 多路复用&#xff08;选择器&#xff09; 无 1.1…

【自动控制原理】时域分析法:一阶、二阶、高阶系统的时间响应及动态性能

文章目录 第3章 时域分析法3.1 基本概念3.1.1 典型输入信号3.1.2 系统动态性能指标 3.2 一阶系统的时间响应及动态性能一阶系统的标准形式&#xff08;尾1标准型&#xff09;3.2.1一阶惯性环节的单位阶跃响应3.2.2一阶惯性环节的单位速度响应3.2.3一阶惯性环节的单位脉冲响应3.…

乌班图 Linux 系统 Ubuntu 23.10.1 发布更新镜像

Ubuntu 团队在其官网上发布了Ubuntu 23.10.1 版本,这是目前较新的 Ubuntu 23.10(Focal Fossa)操作系统系列的第一个发行版,旨在为社区提供最新的安装媒体。Ubuntu 22.04 LTS(Focal Fossa)操作系统系列于 2022 年 4 月 21 日发布。 Ubuntu 23.10 LTS(长期支持版本)可用…

Redis常见风险分析

击穿 概念&#xff1a;在Redis获取某一key时, 由于key不存在, 而必须向DB发起一次请求的行为, 称为“Redis击穿”。 引发击穿的原因&#xff1a; 第一次访问恶意访问不存在的keyKey过期 合理的规避方案&#xff1a; 服务器启动时, 提前写入规范key的命名, 通过中间件拦截对…

5G及其后的5G非地面网络:趋势和研究挑战-HARQ部分

NTN组件纳入5G架构第一步 在NTN SI中定义了一组架构选项。就NT部分而言&#xff0c;已确定了两大类&#xff1a;星载&#xff08;即基于卫星的通信平台&#xff09;和机载&#xff08;即HAPS&#xff09;设备 并行管理HARQ最大进程数 NHARQRTT(NTX−1)2μ NTX&#xff1a;传输…

物理内存的组织形式

由于物理地址是连续的&#xff0c;页也是连续的&#xff0c;每个页大小也是一样的。因而对于任何一个地址&#xff0c;只要直接除一下每页的大小&#xff0c;很容易直接算出在哪一页。每个页有一个结构 struct page 表示&#xff0c;这个结构也是放在一个数组里面&#xff0c;这…