【【C++类与对象(下)】】

news2024/11/25 11:04:10

1. 再谈构造函数

构造函数体赋值

 在创建对象时,编译器会通过调用构造函数,给对象中的各个成员变量一个合适的初始值:

class Date
{
public:
	// 构造函数
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

 虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量
的初始化.

构造函数体中的语句只能将其称为赋初值,而不能称作初始化。
因为初始化只能初始化一次,而构造函数体内可以多次赋值。

比如下面这段

class Date
{
public:
	// 构造函数
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;// 第一次赋值
		_year = 2022;// 第二次赋值
		//...
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个成员变量后面跟一个放在括号中的初始值或表达式。

class Date
{
public:
	// 构造函数
	Date(int year = 0, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

注意事项:
1每个成员变量在初始化列表中只能出现一次
 因为初始化只能进行一次,所以同一个成员变量在初始化列表中不能多次出现。
2、类中包含以下成员,必须放在初始化列表进行初始化:

  • 引用成员变量
  • const成员变量
  • 自定义类型成员(且该类没有默认构造函数时)

下面这个代码因为_x1,_x2没有在定义时就初始化而报错。

class Test
{
public :
	Test()
	{

	}
private:
	 const int _x1;
	 int& _x2;
};

int main()
{

	Test t1;
	return 0;
}

在这里插入图片描述


或者若一个类没有默认构造函数,那么我们在实例化该类对象时就需要传参对其进行初始化,所以实例化没有默认构造函数的类对象时必须使用初始化列表对其进行初始化。

在这里再声明一下,默认构造函数是指不用传参就可以调用的构造函数:
 1.我们不写,编译器自动生成的构造函数。
 2.无参的构造函数。
 3.全缺省的构造函数。

class A //该类没有默认构造函数 
{
public:
	A(int val) //注:这个不叫默认构造函数(需要传参调用)
	{
		_val = val;
	}
private:
	int _val;
};

class B
{
public:
	B()
		:_a(2021) //必须使用初始化列表对其进行初始化
	{}
private:
	A _a; //自定义类型成员(该类没有默认构造函数)
};

总结一下:在定义时就必须进行初始化的变量类型,就必须放在初始化列表进行初始化。

3、尽量使用初始化列表初始化
 因为初始化列表实际上就是当你实例化一个对象时,该对象的成员变量定义的地方,所以无论你是否使用初始化列表,都会走这么一个过程(成员变量需要定义出来)。
严格来说:
 1.对于内置类型,使用初始化列表和在构造函数体内进行初始化实际上是没有差别的.:

2.对于自定义类型,使用初始化列表可以提高代码的效率

class Time
{
public:
	Time(int hour = 0)
	{
		_hour = hour;
	}
private:
	int _hour;
};
class Test
{
public:
	// 使用初始化列表
	Test(int hour)
		:_t(12)// 调用一次Time类的构造函数
	{}
private:
	Time _t;
};

对于以上代码,当我们要实例化一个Test类的对象时,我们使用了初始化列表,在实例化过程中只调用了一次Time类的构造函数。
 我们若是想在不使用初始化列表的情况下,达到我们想要的效果,就不得不这样写了:

class Time
{
public:
	Time(int hour = 0)
	{
		_hour = hour;
	}
private:
	int _hour;
};
class Test
{
public:
	// 在构造函数体内初始化(不使用初始化列表)
	Test(int hour)
	{ //初始化列表调用一次Time类的构造函数(不使用初始化列表但也会走这个过程)
		Time t(hour);// 调用一次Time类的构造函数
		_t = t;// 调用一次Time类的赋值运算符重载函数
	}
private:
	Time _t;
};

首先我们先要明确初始化时的顺序时怎么走的:

  1. 首先先走一遍初始化列表(不管有没有实现)
  2. 然后再走函数体

在了解了具体的赋值顺序之后,我们来看看为什么这样写比用使用初始化列表的效率低:
当我们要实例化一个Test类的对象时,在实例化过程中会先在初始化列表时调用一次Time类的构造函数,然后在实例化t对象时调用一次Time类的构造函数,最后还需要调用了一次Time类的赋值运算符重载函数,效率就降下来了。
所以建议使用初始化列表。

4、成员变量在类中声明的次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后顺序无关
举个例子:

#include <iostream>
using namespace std;
int i = 0;
class Test
{
public:
	Test()
		:_b(i++)
		,_a(i++)
	{}
	void Print()
	{
		cout << "_a:" << _a << endl;
		cout << "_b:" << _b << endl;
	}
private:
	int _a;
	int _b;
};
int main()
{
	Test test;
	test.Print(); //打印结果test._a为0,test._b为1
	return 0;
}

代码中,Test类构造函数的初始化列表中成员变量_b先初始化,成员变量_a后初始化,按道理打印结果test._a为1,test._b为0,但是初始化列表的初始化顺序是成员变量在类中声明次序,所以最终test._a为0,test._b为1。


为了更好的理解这一块的内容,我们来看看这段代码:

class A
{
public:
	A(int val)
	{
		_val = val;
	}
private:
	int _val;	//没有缺省值
};
class B
{
public:
	B()
		:_a(20)
	{}
private:
	A _a;
	int b = 1;	//有缺省值
};

我们能看到A类中有一个内置类型_val B类中有一个自定义类型_a,和一个内置类型b
并且在这两个类的私有域Private中给_val没有赋缺省值但是给b赋缺省值
这一块的缺省值就是在用初始化列表的缺省值
因为每次实例化一个对象时,初始化第一步要走的地方就是去初始化列表找有没有值可赋,如果有就有该值赋值,没有的话就去看有没有缺省值,要是都没有的话就只好赋随机值
所以这一块的代码走出来的结果时:在这里插入图片描述
我们再来看一个:

class A
{
public:
	A(int val)
		//:_val(30)
	{
		_val = val;
	}
private:
	int _val =10;
};
class B
{
public:
	B()
		:_a(20)
		, b(2)
	{
		b = 5;
	}
private:
	A _a;
	int b = 1;
};

这里B类中的函数体也有给b赋值,所以最终的结果是:
在这里插入图片描述
这里建议最好自己手动调试一边,理清楚中间的细节!


同时C++11中也支持这样写:

class A
{
public:
	//explicit A(int a1, int a2)
	A(int a1, int a2)
		:_a1(a1)
		,_a2(a2)
	{}

private:
	int _a1;
	int _a2;
};

int main()
{
	// C++11
	A aa1 = { 1, 2 };
	const A& aa2 = { 1, 2 };

	return 0;
}

explicit关键字

构造函数不仅可以构造和初始化对象,对于单个参数的构造函数,还支持隐式类型转换。

#include <iostream>
using namespace std;
class Date
{
public:
	Date(int year = 0) //单个参数的构造函数
		:_year(year)
	{}
	void Print()
	{
		cout << _year << endl;
	}
private:
	int _year;
};
int main()
{
	Date d1 = 2024; //支持该操作
	d1.Print();
	return 0;
}

在上述实例化d1这个对象时用到了隐式类型转换:
在语法上可以这样理解,先构造一个tmp,再拷贝给d1,该代码可以理解如下:

Date tmp(2024); //先构造
Date d1(tmp); //再拷贝构造

下面这幅图可以更好的帮助理解:

在这里插入图片描述
这里有一个隐式的类型转换,所以可以直接在这里插入图片描述这样简洁写,编译器会自己优化。

但是,对于单参数的自定义类型来说,Date d1 = 2024这种代码的可读性不是很好,我们若是想禁止单参数构造函数的隐式转换,可以用关键字explicit来修饰构造函数

2. Static成员

2.1概念

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

2.2特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
#include <iostream>
using namespace std;
class test
{
private:
	static int _t;
};
int main()
{
	cout << sizeof(test) << endl;
	return 0;
}

在这里插入图片描述
计算的结果是1,因为静态成员_t是存储在静态区的,所以在计算这个类的大小时,静态成员并不计入总大小之和。

  1. 静态成员变量必须在类外定义,定义时不添加static关键字
class Test
{
private:
	static int _n;
};
// 静态成员变量的定义初始化
int Test::_n = 0;

注意:这里静态成员变量_n虽然是私有,但是我们在类外突破类域直接对其进行了访问。这是一个特例,不受访问限定符的限制,否则就没办法对静态成员变量进行定义和初始化了。

  1. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
class A
{
public:
	static int GetNum()
	{
		a++;
		return n;
	}
private:
	static int n;
	int a = 0;

};

这里的GetNum函数是静态成员函数,无法访问到a,所以编译出现错误:
在这里插入图片描述
**小贴士:**含有静态成员变量的类,一般含有一个静态成员函数,用于访问静态成员变量。

  1. 访问静态成员变量的方法
    (1).当静态成员变量为公有时,有以下几种访问方式:
class test
{
public:
	static int _n;
};

int test::_n = 0;	//静态成员变量的初始化

int main()
{
	test t;
	
	t._n++;			//通过类对象突破类域来访问
	test::_n++;		//通过类名突破类域来访问
	test()._n;		//通过匿名对象突破类域来访问
}

(2).当静态成员变量为私有时,有以下几种访问方式:

class test
{
public:
	static int GetN()
	{
		return _n;
	}
private:
	static int _n;
};

int test::_n = 0;	//静态成员变量的初始化

int main()
{
	test t;

	t.GetN();			//通过类对象突破类域来访问
	test::GetN();		//通过类名突破类域来访问
	test().GetN;		//通过匿名对象突破类域来访问
}
  1. 静态成员和类的普通成员一样,也有public、private和protected这三种访问级别
     所以当静态成员变量设置为private时,尽管我们突破了类域,也不能对其进行访问。

为了巩固已学知识,我们来看一看下面这两个问题:
 1、静态成员函数可以调用非静态成员函数吗?
 2、非静态成员函数可以调用静态成员函数吗?

1:不可以。因为非静态成员函数的第一个形参默认为this指针,而静态成员函数中没有this指针,故静态成员函数不可调用非静态成员函数。
2:可以因为静态成员函数和非静态成员函数都在类中,在类中不受访问限定符的限制。

3. 友元

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

3.1友元函数

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

我们可以用一个例子来帮助理解这个友元函数:小王和小明是好朋友,小王今天去小明家做客,那么小明就会用家里的水果来招待小王。
这里的水果就指的类的内部变量,小王去小明家做客就是要把小王这个类在小明家用friend友元声明,所以小王就可以访问小明的私有变量。


 对于之前实现的日期类,我们现在尝试重载operator<<,但是我们发现没办法将其重载为成员函数,因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置:this指针默认是第一个参数,即左操作数,但是实际使用中cout需要是第一个形参对象才能正常使用。

比如:

class Date
{
public:
	Date(int year,int month,int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
	void operator<<(ostream& out)
	{
		out << _year << "年" << _month << "月" << _day << "日" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024, 2, 10);
	d1 << cout;		//这里的对象是反的
	return 0;
}

在这里插入图片描述

所以我们要将operator<<重载为全局函数,但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。(operator>>同理)

class Date
{
	friend void operator<<(ostream& out,Date& d);	//友元声明,需要访问私有成员。
public:
	Date(int year,int month,int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
	
private:
	int _year;
	int _month;
	int _day;
};

void operator<<(ostream& out,Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
}

int main()
{
	Date d1(2024, 2, 10);
	cout << d1;
	return 0;
}

在这里插入图片描述

 我们都知道C++的<<和>>很神奇,因为它们能够自动识别输入和输出变量的类型,我们使用它们时不必像C语言一样增加数据格式的控制。实际上,这一点也不神奇,内置类型的对象能直接使用cout和cin输入输出,是因为库里面已经将它们的<<和>>重载好了,<<和>>能够自动识别类型,是因为它们之间构成了函数重载。

class Date
{
	friend ostream& operator<<(ostream& out,Date& d);
	friend istream& operator>>(istream& in, Date& d);
public:
	Date()
	{

	}
	Date(int year,int month,int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
	
private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& out,Date& d)	// << 运算符重载
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)	// >> 运算符重载
{
	cout << "请依次输入年月日>" << endl;
	in >> d._year >> d._month >> d._day ;
	return in;
}

友元函数说明:
 1、友元函数可以访问类是私有和保护成员,但不是类的成员函数。
 2、友元函数不能用const修饰。
 3、友元函数可以在类定义的任何地方声明,不受访问限定符的限制。
 4、一个函数可以是多个类的友元函数。
 5、友元函数的调用与普通函数的调用原理相同。

3.2友元类

 友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一在这里插入代码片个类中非公有成员。

class A
{
	// 声明B是A的友元类
	friend class B;
public:
	A(int n = 0)
		:_n(n)
	{}
private:
	int _n;
};
class B
{
public:
	void Test(A& a)
	{
		// B类可以直接访问A类中的私有成员变量
		cout << a._n << endl;
	}
};

友元类说明
1、友元关系是单向的,不具有交换性。
 例如上述代码中,B是A的友元,所以在B类中可以直接访问A类的私有成员变量,但是在A类中不能访问B类中的私有成员变量。
2、友元关系不能传递。
 如果A是B的友元,B是C的友元,不能推出A是C的友元。


4. 内部类

概念:如果一个类定义在另一个类的内部,则这个类被称为内部类。
注意内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访
问外部类中的所有成员。但是外部类不是内部类的友元。

特性:

  • 内部类可以定义在外部类的public、protected、private都是可以的。
  • 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  • sizeof(外部类)=外部类,和内部类没有任何关系。
class A
{
private:
	static int k;
	int h;
public:
	class B // B天生就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
	A::B b;
	b.foo(A());
}

下面的这段代码的大小是4,外部类的大小和内部类无关

#include <iostream>
using namespace std;
class A //外部类
{
public:
	class B //内部类
	{
	private:
		int _b;
	};
private:
	int _a;
};
int main()
{
	cout << sizeof(A) << endl; //外部类的大小
	return 0;
}

5.匿名对象

匿名对象我们现在先只简单做以了解其基本特性,后续还会继续学习。

匿名对象的声明周期与其他不一样,他的生命周期只在其定义的这一行,代码运行到下一行就会自动销毁:

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

int main()
{
	A();
	A();
	A();

	return 0;
}

在这里插入图片描述

6.拷贝对象时的一些编译器优化

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a = aa._a;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
void f1(A aa)
{}
A f2()
{
	A aa;
	return aa;
}
int main()
{
	// 传值传参
	A aa1;
	f1(aa1);
	cout << endl;
	// 传值返回
	f2();
	cout << endl;
	// 隐式类型,连续构造+拷贝构造->优化为直接构造
	f1(1);
	// 一个表达式中,连续构造+拷贝构造->优化为一个构造
	f1(A(2));
	cout << endl;
	// 一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造
	A aa2 = f2();
	cout << endl;
	// 一个表达式中,连续拷贝构造+赋值重载->无法优化
	aa1 = f2();
	cout << endl;
	return 0;
}

在这里插入图片描述

  1. 按值传递:当使用按值传递(f1(aa1))调用f1()时,会调用拷贝构造函数A(const A& aa)来在函数作用域内创建aa1的副本。然后,在f1()退出时,局部副本的析构函数~A()被调用。

  2. 按值返回:在f2()中,创建一个A对象aa并按值返回。这涉及构造aa,然后按值返回它,调用拷贝构造函数A(const A& aa)创建返回的临时副本。然后,当临时对象超出作用域时,调用其析构函数。

  3. 隐式类型转换:当调用f1(1)时,整数1被隐式转换为A对象,使用构造函数A(int a)。然后,这个临时的A对象被按值传递给f1(),调用拷贝构造函数A(const A& aa)。最后,临时对象被销毁。

  4. 带临时对象的隐式类型转换:f1(A(2))涉及使用构造函数A(int a)创建临时A对象,然后将其按值传递给f1()。这与前一个情况类似,但是直接在函数调用中构造了临时对象。

  5. 链式拷贝构造函数:在A aa2 = f2();中,f2()按值返回一个A对象,调用构造函数A(int a)创建一个局部对象。然后,使用拷贝构造函数A(const A& aa)将这个局部对象复制到aa2中。然后,随着对象超出作用域,析构函数被调用。

  6. 拷贝赋值:aa1 = f2();涉及在f2()内部创建一个临时对象,然后将其赋值给aa1。这触发了拷贝构造函数来创建临时对象,然后触发了赋值运算符A& operator=(const A& aa)将其赋值给aa1。最后,临时对象被销毁。

7. 再次理解封装

C++是基于面向对象的程序,面向对象有三大特性:封装、继承、多态。

C++中,类将一个事物的属性和行为组合在一起,更符合人们对于事物的认知,使得对象的所有相关内容都能被封装在一起。通过访问限定符,部分功能得以开放,使得对象可以与其他对象进行交互。而对于对象内部的一些实现细节,外部用户无需了解,有时即使了解也无益,反而会增加使用和维护的难度,使得事物变得复杂化。

当你准备去旅行时,你可能会准备一个行李箱。这个行李箱就像一个对象,它有自己的属性和行为,而这些属性和行为是封装在一起的。
在这里插入图片描述
1. 属性:行李箱有大小、颜色、重量等属性。这些属性描述了行李箱的特征,但其他人不需要了解行李箱内部是如何设计的。

2. 行为:行李箱可以打开、关闭、装入物品、拉动等。这些行为是行李箱可以执行的操作,其他人只需要知道如何使用行李箱的这些功能,而不需要了解它们是如何实现的。

通过封装,行李箱的内部细节被隐藏起来,只暴露了一些对外公开的接口,使得其他人可以方便地使用它。这样,就可以避免其他人无意间改变了行李箱的设计,也不需要其他人关心行李箱内部是如何组织的。

8.再次理解面向对象

 在类和对象阶段,大家一定要体会到,类是对某一类实体(对象)来进行描述的,描述该对象具有那些属性,那些方法,描述完成后就形成了一种新的自定义类型,才用该自定义类型就可以实例化具体的对象。
在这里插入图片描述

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

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

相关文章

Acwing---836. 合并集合

合并集合 1.题目2.基本思想3.代码实现 1.题目 一共有 n n n 个数&#xff0c;编号是 1 ∼ n 1∼n 1∼n&#xff0c;最开始每个数各自在一个集合中。 现在要进行 m m m 个操作&#xff0c;操作共有两种&#xff1a; M a b&#xff0c;将编号为 a a a 和 b b b 的两个数所…

Netty应用(二) 之 ByteBuffer

目录 4.ByteBuffer详解 4.1 ByteBuffer为什么做成一个抽象类&#xff1f; 4.2 ByteBuffer是抽象类&#xff0c;他的主要实现类为 4.3 ByteBuffer的获取方式 4.4 核心结构&#xff08;NIO的ByteBuffer底层是啥结构&#xff0c;以及读写模式都是根据这些核心结构进行维护的&a…

【JavaScript 漫游】【014】正则表达式通关

文章简介 JS 语言中的 RegExp 对象提供正则表达式的功能。本篇文章旨在对该对象的相关知识点进行总结。内容包括&#xff1a; 正则表达式概述RegExp 对象的实例属性RegExp 对象的实例方法字符串与正则表达式相关的实例方法正则表达式匹配规则 概述 正则表达式的概念 正则表…

linux 08 文件查找

02. 第一. alias 第二. locate&#xff1a; locate 找不到最近的文件 更新locate 后

Spring Cloud Hystrix 参数配置、简单使用、DashBoard

Spring Cloud Hystrix 文章目录 Spring Cloud Hystrix一、Hystrix 服务降级二、Hystrix使用示例三、OpenFeign Hystrix四、Hystrix参数HystrixCommand.Setter核心参数Command PropertiesFallback降级配置Circuit Breaker 熔断器配置Metrix 健康统计配置Request Context 相关参数…

Flink 2.0 状态存算分离改造实践

本文整理自阿里云智能 Flink 存储引擎团队兰兆千在 FFA 2023 核心技术&#xff08;一&#xff09;中 的分享&#xff0c;内容关于 Flink 2.0 状态存算分离改造实践的研究&#xff0c;主要分为以下四部分&#xff1a; Flink 大状态管理痛点 阿里云自研状态存储后端 Gemini 的存…

基于Java (spring-boot)的考勤管理系统

一、项目介绍 普通员工功能&#xff1a; &#xff08;1&#xff09;登录&#xff1a;员工进入界面后需要输入自己的账号密码进行登录。 &#xff08;2&#xff09;签到打卡&#xff1a;员工登录完成以后&#xff0c;可以进行签到打卡。 &#xff08;3&#xff09;修改密码&a…

mac卸载被锁定的app

sudo chflags -hv noschg /Applications/YunShu.app 参考&#xff1a;卸载云枢&#xff08;MacOS 版&#xff09;

从左值和右值的角度分析a++和++a

摘自牛客上的一个题目&#xff1a; int a5,则 (a)的值是? 答案是会编译报错。 原因&#xff1a; a返回的是右值(rvalue)&#xff0c;而我们不能对一个右值进行自增操作。所以(a)会报错。 怎么理解呢&#xff1f; &#xff08;a)返回的是a在1之前的值&#xff0c;这个值是一个…

git revert回退某次提交

请直接看原文: 【git revert】使用以及理解&#xff08;详解&#xff09;_git revert用法-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- 前言 试验得知:用Reset HEAD方…

一、西瓜书——绪论

第一章 绪论 1.独立同分布 通常 假设 样本空间 中 全 体样 本 服 从 一 个 未 知 “ 分 布 ” ( d i s t r i b u t i o n ) D , 我们获得的每个样本都是独立地从这个分布上采样获得的&#xff0c; 即 “ 独 立同 分布 ” ( i n d e p e n d e n t a n d i d e n t ic a …

Flutter 网络请求之Dio库

Flutter 网络请求之Dio库 前言正文一、配置项目二、网络请求三、封装① 单例模式② 网络拦截器③ 返回值封装④ 封装请求 四、结合GetX使用五、源码 前言 最近再写Flutter系列文章&#xff0c;在了解过状态管理之后&#xff0c;我们再来学习一下网络请求。 正文 网络请求对于一…

EMC学习笔记(二十二)降低EMI的PCB设计指南(二)

降低EMI的PCB设计指南&#xff08;二&#xff09; 1.电源和地概述2.电感量3.两层板和四层板4.单层和双层设计中的微控制器接地5.信号返回地6.模拟、数字信号与大功率电源7.模拟电源引脚和模拟参考电源8.四层板电源设计参考注意事项 tips&#xff1a;资料主要来自网络&#xff0…

ChatGpt报错:We ran into an issue while authenticating you解决办法

在登录ChatGpt时报错&#xff1a;Oops&#xff01;,We ran into an issue while authenticating you.(我们在验证您时遇到问题)&#xff0c;记录一下解决过程。 完整报错&#xff1a; We ran into an issue while authenticating you. If this issue persists, please contact…

Vue3中使用element-plus菜单折叠后文字不消失

今天使用element-plus中国的导航菜单时&#xff0c;发现菜单栏折叠起来时文字不会自动消失&#xff0c;因为element-plus中内置了菜单折叠文字自动消失的&#xff0c;使用collapsetrue/false即可&#xff0c;但在实际使用中出现了一下问题&#xff1a; 折叠以后文字并没有消失&…

学了很多知识,没多久就忘光了,怎么办?

读了很多书&#xff0c;回想起来&#xff0c;却总是觉得一片空白&#xff0c;想不出究竟留下了些什么&#xff1b; 付费参加了一堆课程&#xff0c;听的时候觉得醍醐灌顶&#xff0c;没过多久却发现都还给了老师&#xff1b; 看文章、听讲座&#xff0c;记了一大堆东西&#xf…

解决挂梯子 无法正常上网 的问题

方法&#xff1a; 打开 控制面板 &#x1f449; 网络和Internet &#x1f449; Internet选项 &#x1f449; 连接 &#x1f449; 局域网设置 &#x1f449; 代理服务器 &#x1f449; 取消选项 有问题可参考下图

代码随想录算法训练营第四十九天(动态规划篇之01背包)| 474. 一和零, 完全背包理论基础

474. 一和零 题目链接&#xff1a;https://leetcode.cn/problems/ones-and-zeroes/submissions/501607337/ 思路 之前的背包问题中&#xff0c;我们对背包的限制是容量&#xff0c;即每个背包装的物品的重量和不超过给定容量&#xff0c;这道题的限制是0和1的个数&#xff0…

【十五】【C++】list的简单实现

list 的迭代器解引用探究 /*list的迭代器解引用探究*/ #if 1 #include <list> #include <vector> #include <iostream> #include <algorithm> using namespace std;class Date {private:int _year;int _month;int _day;public:Date(): _year(2024), _m…

Linux中孤儿/僵尸进程/wait/waitpid函数

孤儿进程&#xff1a; 概念&#xff1a;若子进程的父进程已经死掉&#xff0c;而子进程还存活着&#xff0c;这个进程就成了孤儿进程。 为了保证每个进程都有一个父进程&#xff0c;孤儿进程会被init进程领养&#xff0c;init进程成为了孤儿进程的养父进程&#xff0c;当孤儿…