【C++】类和对象——Lesson1

news2024/9/20 22:32:30

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
💥💥个人主页:奋斗的小羊
💥💥所属专栏:C++

🚀本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为记录我的学习过程及理解。文笔、排版拙劣,望见谅。


目录

  • 1、类的定义
    • 1.1类定义格式
    • 1.2访问限定符
    • 1.3类域
  • 2、实例化
    • 2.1什么是实例化
    • 2.2对象大小
    • 2.3 this指针
  • 3、C++和C语言实现Stack对比
  • 4、类的默认成员函数
    • 4.1构造函数
    • 4.2析构函数
    • 4.3拷贝构造函数

1、类的定义

C语言结构体中只能定义变量,C++中结构体内不仅可以定义变量还可以定义函数。

1.1类定义格式

class ClassName
{
	//类体:成员函数和成员变量
};
  • class为定义类的关键字,ClassName为类的名字,{ }中为类的主体
  • 类中的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数
  • C++中struct也可以定义类,C++兼容C中struct的用法,同时也升级struct成了类,一般情况下还是常用class定义类
  • 定义在类里面的成员函数默认为inline
class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	//为了区分成员变量,一般习惯
	//给成员变量加一个标识
	int _year;
	int _month;
	int _day;
};

//不再需要typedef,ListNode就可以代表类型
struct ListNode
{
	int val;
	ListNode* next;
};
  • 类的两种定义方式:声明和定义全部放在类体中 / 类声明放在.h文件中,成员函数定义在.cpp文件中,成员函数名前需要加类名

1.2访问限定符

  • C++一种实现封装的方式,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将接口(函数)提供给外部的用户使用

在这里插入图片描述

  • public修饰的成员在类外可以直接被访问,protectedprivate修饰的成员在类外不能直接被访问
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止
  • class定义成员没有被访问限定符修饰时默认privatestruct默认为public

1.3类域

  • 类定义了一个新的作用域,类的所有成员都在类的作用域中,在类外定义成员时,需要使用::作用域操作符指明成员属于哪个类域
  • 类域影响的是编译的查找规则,编译器默认只会在局部和全局查找,只有指定类域才会到类域中区查找

2、实例化

2.1什么是实例化

  • 用类类型在物理内存中创建对象的过程,称为类实例化出对象
  • 类是对象进行一种抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时才会分配空间
  • 类和对象是一对多的关系,类就像设计图一样,不能存储数据
class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	//这里只是声明,没有开空间
	int _year;
	int _month;
	int _day;
};

2.2对象大小

类实例化出的每个对象,都有独立的数据空间,每个对象都有各自独立的成员变量存储各自的数据,那成员函数是否被存储呢?
如果存储的话要存函数指针,但是函数指针不会变,也就是说每个对象中的函数指针都是一样的,如果类实例化很多对象成员函数指针就要被重复存储很多次,有点浪费。
其实函数指针是不需要存储的,函数指针是一个地址,编译器在编译链接时就找到函数的地址,不是在运行时找。

类实例化出对象中只存储成员变量,C++规定类实例化的对象也要遵从内存对齐的规则。

class A
{
public:
	void Print()
	{
		cout << _ch << endl;
	}
private:
	char _ch;
	int _i;
};

class B
{
public:
	void Print()
	{
		//
	}
};

class C
{};

int main()
{
	A a;
	B b;
	C c;
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	cout << sizeof(c) << endl;
	return 0;
}

请添加图片描述

对象b和c没有成员变量,但大小还是1,给1字节是为了占位标识对象存在。


2.3 this指针

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _ch << endl;
	}
private:
    int _year;
	int _month;
	int _day;
	char _ch;
	int _i;
}
int main()
{
	Date d1;
	Date d2;
	
	d1.Init(2024, 7, 27);
	d1.Print();

	d2.Init(2004, 11, 7);
	d2.Print();
	
	return 0;
}

Date类中有InitPrint两个成员函数,函数体中没有关于不同对象的区分,那当d1调用InitPrint函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?

  • 编译器编译后,类的成员函数默认都会在形参的第一个位置增加一个当前类型的指针,叫做this指针void Init(Date* const this, int year, int month, int day)
  • 类的成员函数中访问成员变量本质都是通过this指针访问的,C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针
  • this指针不能被修改,指向的内容可以修改
  • this指针存在内存中的栈区(形参)

也就是说上面的代码本质是下面这样的,但不能这样写:

class Date
{
public:
	void Init(Date* const this, int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print(Date* const this)
	{
		cout << this->_ch << endl;
	}
private:
    int _year;
	int _month;
	int _day;
	char _ch;
	int _i;
}
int main()
{
	Date d1;
	Date d2;
	
	d1.Init(&d1, 2024, 7, 27);
	d1.Print(&d1);

	d2.Init(&d2, 2004, 11, 7);
	d2.Print(&d2);
	
	return 0;
}

| 例一:

下面程序编译运行结果是什么?

#include <iostream>
using namespace std;

class A
{
public:
	void Print()
	{
		cout << "A::Print" << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

p->Print();这句代码并没有对指针解引用,->这里是成员访问操作符,p是对象指针,值为nullptr,就像下面这样将对象地址传过去由this指针接收,因为p本身就是对象地址所以不用再取地址

Date d1;
d1.Print(&d1);

请添加图片描述

底层汇编代码是这样的:

在这里插入图片描述

上面程序编译运行结果是:正常运行

在这里插入图片描述

| 例二:

下面程序编译运行结果是什么?

#include <iostream>
using namespace std;

class A
{
public:
	void Print()
	{
		cout << _a << endl;
		cout << "A::Print" << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

这个题的运行结果是:运行崩溃

和例一基本一致,运行崩溃的原因是:cout << _a << endl;,因为例一说了this指针为空指针,cout << this->_a << endl;对空指针解引用了。


3、C++和C语言实现Stack对比

面向对象三大特性:封装、继承、多态,通过下面的对比我们可以初步了解封装。

C语言实现Stack:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

void STDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	// 满了, 扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *
			sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}

bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	while (!STEmpty(&s))
	{
		printf("%d\n", STTop(&s));
		STPop(&s);
	}
	STDestroy(&s);
	return 0;
}

C++实现Stack

#include <iostream>
#include <assert.h>
using namespace std;

typedef int STDataType;

class Stack
{
public:
	// 成员函数
	void Init(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
}
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	int Top()
	{
		assert(_top > 0);
		return _a[_top - 1];
	}
	void Destroy()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	// 成员变量
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

int main()
{
	Stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);
	while (!s.Empty())
	{
		printf("%d\n", s.Top());
		s.Pop();
	}
	s.Destroy();
	return 0;
}
  • C++中数据和函数都放到了类里面,通过访问限定符进行了限制,不能再随意通过对象直接修改数据,这是C++封装的一种体现,这是最重要的变化。这里分装的本质是一种更严格规范的管理,避免乱访问修改的问题
  • C++中有一些相对方便的语法,比如Init 给缺省参数会方便很多,成员函数每次不需要传对象地址,因为this指针隐含的传递了,使用类型也不再需要typedef重定义类名

4、类的默认成员函数

默认成员函数就是用户没有显示实现,编译器会自动生成的成员函数称为默认成员函数。
一个类,我们不写的情况下编译器会默认生成以下6个成员函数,默认成员函数很重要,也比较复杂,我们要从两个方面去学习。

  1. 我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求
  2. 编译器默认生成的函数不满意我们的需求,我们如何自己实现?

在这里插入图片描述


4.1构造函数

构造函数是特殊的成员数,需要注意的是,构造函数虽然名叫构造,但构造函数的主要任务并不是开空间创建对象,而是对象实例化时初始化对象。
我们常用的局部对象是栈帧创建时空间就开好了, 构造函数的本质是要替代我们以前StackDate类中写的Init函数的功能,构造函数自动调用的特点就完美的替代了Init

构造函数的特点:

  1. 函数名和类名相同
  2. 无返回值(返回值啥都不需要给,也不需要写void)
  3. 对象实例化时系统会自动调用对应的构造函数
  4. 构造函数可以重载
  5. 如果类中没有显示定义构造函数,C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义编译器将不再生成
  6. 无参构造函数、全缺省构造函数、我们不写构造函数时编译器默认生成的构造函数,都叫默认构造函数, 但是这三个函数有且只有一个存在,不能同时存在,无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义
  7. 不传实参就可以调用的构造就叫默认构造
#include <iostream>
using namespace std;

class Date
{
public:
	// 1.⽆参构造函数
	Date()
	{
		_year = 1;
		_month = 1;
		_day = 1;
	}
	// 2.带参构造函数
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	// 3.全缺省构造函数
	/*Date(int year = 1, int month = 1, int day = 1)
	{
	_year = year;
	_month = month;
	_day = day;
	}*/
	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	// 如果留下三个构造中的第⼆个带参构造,第⼀个和第三个注释掉
	// 编译报错:error C2512: “Date”: 没有合适的默认构造函数可⽤
	Date d1; // 调⽤默认构造函数
	Date d2(2025, 1, 1); // 调⽤带参的构造函数
	// 注意:如果通过⽆参构造函数创建对象时,对象后⾯不⽤跟括号,否则编译器⽆法
	// 区分这⾥是函数声明还是实例化对象
	// warning C4930: “Date d3(void)”: 未调⽤原型函数(是否是有意⽤变量定义的?)
	Date d3();
	d1.Print();
	d2.Print();
	return 0;
}
  1. 我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是否初始化是不确定的,看编译器。对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要用初始化列表才能解决
typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};
// 两个Stack实现队列
class MyQueue
{
public:
	//编译器默认⽣成MyQueue的构造函数调⽤了Stack的构造,完成了两个成员的初始化
private:
	Stack pushst;
	Stack popst;
};
int main()
{
	MyQueue mq;
	return 0;
}

大多数情况下,构造函数都需要我们自己写,应写尽写


4.2析构函数

析构函数和构造函数功能相反, 析构函数不是完成对对象本身的销毁,比如局部对象是存在栈帧的,函数结束栈帧销毁,不需要我们管;C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。
析构函数的功能类比我们之前Stack实现的Destroy功能,而像Date没有Destroy,其实就是没有资源需要释放,所以严格说Date是不需要析构函数的。

析构函数的特点:

  1. 析构函数名是在类名前加上字符~
  2. 无参数无返回值(和构造类似,也不需要加void
  3. 一个类只能有一个析构函数,若未显示定义,系统会自动生成默认的析构函数
  4. 对象生命周期结束时,系统会自动调用析构函数
  5. 跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定义类型成员会调用它的析构函数
  6. 我们显示写析构函数,对于自定义类型成员也会调用它的析构,也就是说自定义类型成员无论什么情况都会自动调用析构函数
  7. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,如Date;如果默认生成的析构就可以用,也就不需要显示写析构,如MyQueue;但是有资源申请时,一定要自己写析构,否则会造成资源泄露,如Stack
  8. 一个局部域的多个对象,C++规定后定义的先析构
#include<iostream>
using namespace std;
typedef int STDataType;

class Stack
{
public:
	//默认构造函数
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	//析构函数
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

// 两个Stack实现队列
class MyQueue
{
public:
	//编译器默认⽣成MyQueue的析构函数调⽤了Stack的析构,释放的Stack内部的资源
	
	// 显⽰写析构,也会⾃动调⽤Stack的析构
	/*~MyQueue()
	{}*/

private:
	Stack pushst;
	Stack popst;
};
int main()
{
	Stack st;
	MyQueue mq;
	return 0;
}

析构函数的意义主要在于相较于C语言我们不需要再写InitDestroy,方便了很多。


4.3拷贝构造函数

如果一个构造函数的第一个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造函数是一个特殊的构造函数。

拷贝构造的特点:

  1. 拷贝构造函数是构造函数的一个重载
  2. 拷贝构造函数的第一个参数必须是类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用(如果要传值传参,则会调用拷贝构造,如果拷贝构造函数第一个参数不是引用而是传值传参,而传值传参又要调用拷贝构造,无限递归)
#include <iostream>
using namespace std;

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

	//加上const保护被拷贝对象不被改变
	//传引用一般都要加const
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

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

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

int main()
{
	Date d1(2024, 7, 29);
	d1.Print();

	//拷贝构造
	Date d2(d1);
	//Date d2(&d2, d1);
	d2.Print();

	return 0;
}
  1. C++规定自定义类型对象进行拷贝行为(传值传参)必须调用拷贝构造,所自定义类型传值传参和传值返回都要调用拷贝构造完成
    (所以对于自定义类型来说,不建议使用传值传参,传引用传参可以减少拷贝)

  2. 若未显示定义拷贝构造,编译器会自动生成拷贝构造函数,自动生成的拷贝构造对内置类型成员变量拷贝构造对内置类型也处理)会完成值拷贝 / 浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用它的拷贝构造

也就是说即使我们不显示的写拷贝构造函数,编译器自动生成的拷贝构造也会将d1拷贝给d2

请添加图片描述

既然拷贝构造对内置类型和自定义类型都会用默认生成的拷贝构造完成拷贝,那我们还需要自己写拷贝构造吗?
肯定还是需要我们自己动手写的,如果用默认生成的拷贝构造完成对自定义类型的拷贝,会出现下面这种结果:

在这里插入图片描述

  1. Date这样的类成员变量全是内置类型且没有指向什么资源,编译器自动生成的拷贝构造就可以完成需要的拷贝,所以不需要我们显示实现拷贝构造。像Stack这样的类,虽然也都是内置类型,但是_a指向了资源,编译器自动生成的拷贝构造完成的值拷贝 / 浅拷贝不符合我们的需求,所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部主要是自定义类型Stack成员,编译器自动生成的拷贝构造会调用Stack的拷贝构造,也不需要我们显示实现MyQueue的拷贝构造。如果一个类显示实现了析构并释放资源,那么它就需要显示写拷贝构造,否则不需要。
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

typedef int STDataType;

class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc fail");
			return;
		}
		_capacity = n;
		_top = 0;
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			STDataType* tmp = (STDataType*)realloc(_a, sizeof(STDataType) * 2 * _capacity);
			if (nullptr == tmp)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			tmp = nullptr;
			_capacity *= 2;
		}
		_a[_top] = x;
		_top++;
	}

	Stack(const Stack& st)
	{
		//需要对_a指向资源创建同样大小的资源再拷贝值
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc fail");
			return;
		}
		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}

	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

private:
	STDataType* _a;
	int _top;
	int _capacity;
};

//两个栈实现队列
class MyQueue
{
public:
	//...
private:
	Stack pushst;
	Stack popst;
};

int main()
{
	Stack st1;
	st1.Push(1);
	st1.Push(2);
	st1.Push(3);

	//如果我们不显示实现拷贝构造,则编译器自动生成的拷贝构造会完成浅拷贝
	//会导致st1和st2⾥⾯的_a指针指向同⼀块资源,析构时会析构两次,程序崩溃

	//下面这两种实现的效果一样
	//Stack st2(st1);
	Stack st2 = st1;

	MyQueue mq1;
	//MyQueue⾃动⽣成的拷⻉构造,会⾃动调⽤Stack拷⻉构造完成pushst/popst
	//的拷⻉
	//只要Stack拷⻉构造⾃⼰实现了深拷⻉,他就没问题
	MyQueue mq2 = mq1;

	return 0;
}
  1. 传值返回会产生一个临时对象调用拷贝构造,传值引用返回返回的是返回对象的别名(引用),没有产生拷贝。但是如果返回对象是一个当前函数局部域的局部对象,函数结束就销毁了,那么使用引用返回是有问题的,这时的引用相当于一个野引用,类似野指针。传引用返回可以减少拷贝,但是一定要确保返回对象,在当前函数结束后还在,才能用引用返回

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

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

相关文章

【Golang 面试 - 基础题】每日 5 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

关联映射和缓存机制学习笔记

学习视频&#xff1a;4001 关联映射概述_哔哩哔哩_bilibili~4007 案例&#xff1a;商品的类别_哔哩哔哩_bilibili 目录 1.关联映射概述 1.1关联映射关系 一对一关系 一对多关系 多对多关系 Java对象如何描述事物之间的关系 1.2一对一查询 元素 a.嵌套查询方式 b.嵌套结果方…

Spring Cache常用注解

依赖代码如下&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency> 常用注解详解 1. Cacheable 作用&#xff1a;主要用于配置方法&#xff0c;使其…

第九届全球渲染大赛来了!CG爱好者准备好了吗!

在CG界的日历上&#xff0c;二月和八月总是特别繁忙的月份。这两个月&#xff0c;全球CG艺术界最盛大的赛事——全球渲染大赛&#xff0c;都会开放报名&#xff0c;吸引着世界各地的CG艺术家和爱好者参与。备受期待的第九届全球渲染大赛&#xff0c;已经定于2024年8月3日在美国…

微信私域运营工具分享

解决微信多管理难的问题&#xff0c;多微信工作重复做&#xff0c;效率低的问题&#xff0c;防止飞单、删除客户&#xff0c;解决私域运营的难题

在双碳目标下,如何实现工厂的数字化改造升级

在"双碳"目标下&#xff0c;如何实现工厂的数字化改造升级 在“双碳”目标&#xff0c;即2030年前实现碳达峰、2060年前实现碳中和的宏伟蓝图下&#xff0c;企业作为经济社会活动的主体&#xff0c;其改造升级不仅是响应国家战略的必然要求&#xff0c;也是实现可持…

软件压力测试知识大揭秘,专业软件测评公司推荐

在信息技术迅猛发展的今天&#xff0c;软件已经成为各个行业运作的核心。有助于提升工作效率和管理水平的&#xff0c;软件的稳定性和性能也变得尤为重要。而软件压力测试&#xff0c;作为一种重要的测试手段&#xff0c;逐渐受到了更多企业的重视。 软件压力测试&#xff0c;…

【ROS 最简单教程 001/300】ROS 概念介绍

ROS&#xff1a;Robot Operating System 【适用于机器人的开源元操作系统】 ROS Plumbing Tools Capabilities Ecosystem 通讯 Plumbing ⭐ 实现ROS不同节点之间的交互工具 Tools ⭐ 工具软件包 (ROS中的开发和调试工具)&#xff0c;提供 仿真 功能&#xff1b;功能 Capabi…

图文好物和无人直播实操:定位/涨粉/养号/橱窗/作品/制作/剪辑/开播/等等

1.前言 各位小伙伴大家好&#xff0c;这里是天夏共创&#xff0c;免费分享副业/创业精品项目资源&#xff0c;打破互联网创业/副业信息壁垒&#xff0c;和您一起共享副业/创业项目资源&#xff0c;开启智能化创业/副业新时代&#xff01;致力于每天免费分享全网互联网精品VIP项…

React类组件生命周期与this关键字

类组件生命周期 参考链接 一图胜千言&#xff08;不常用的生命周期函数已隐藏&#xff09; 代码&#xff1a; //CC1.js import { Component } from "react";export default class CC1 extends Component {constructor(props) {super(props);console.log("con…

基于IDEA+Mysql+SpringBoot开发的社区养老服务管理系统

基于IDEAMysqlSpringBoot开发的社区养老服务管理系统 项目介绍&#x1f481;&#x1f3fb; node -version 14.21.3 在当前社会老龄化趋势日益加剧的背景下&#xff0c;构建一个高效、便捷的社区网养老服务管理系统显得尤为重要。本项目基于Spring Boot框架开发&#xff0c;旨…

网站打不开怎么办,收藏以备不时之需

DNS设置示范教程 部分地区有使用移动网络的小伙伴们吐槽无法访问部分网站的情况&#xff0c;同样的网站&#xff0c;使用电信和联通的用户就能正常访问。 这其实有很大几率是由于运营商的网络问题导致的&#xff0c;容易出现网站打不开的结果。 要解决移动网络无法访问的情况…

【React Hooks原理 - useTransition】

概述 在上一篇中我们介绍了useDeferredValue的基本原理&#xff0c;本文主要介绍一下useTransition这个Hook&#xff0c;之所以在这里提到useDeferredValue&#xff0c;是因为这两个Hook都是在React18引入的进行渲染优化的Hooks&#xff0c;在某些功能上是重叠的&#xff0c;主…

YOLO入门教程(一)——训练自己的模型【含教程源码 + 故障排查】

目录 引言前期准备Step1 打标训练Step2 格式转换Step3 整理训练集Step4 训练数据集4.1创建yaml文件4.2训练4.3故障排查4.3.1OpenCV版本故障&#xff0c;把OpenCV版本升级到4.0以上4.3.2NumPy版本故障&#xff0c;把NumPy降低版本到1.26.44.3.3没有安装ultralytics模块4.3.4Aria…

自闭症儿童上学指南:帮助孩子适应校园生活

在自闭症儿童成长的道路上&#xff0c;校园生活是他们融入社会、学习新知、发展社交技能的重要一步。作为星启帆自闭症儿童康复机构&#xff0c;我们深知这一过程对于孩子及其家庭而言既充满挑战也极具意义。 一、前期准备&#xff1a;建立坚实的支持体系 1. 深入了解孩子需求 …

【机器学习】梯度下降函数如何判断其收敛、学习率的调整以及特征缩放的Z-分数标准化

#引言 在机器学习中&#xff0c;特征缩放和学习率是两个非常重要的概念&#xff0c;它们对模型的性能和训练速度有显著影响。 特征缩放是指将数据集中的特征值缩放到一个固定的范围内&#xff0c;通常是在0到1之间或者标准化到均值为0、方差为1。特征缩放对于模型的训练至关重要…

Vmware安装openstack

安装虚拟机 创建完成后&#xff0c;点击开启虚拟机 稍等执行成功后 上传压缩包到指定目录。将yoga_patch.tar.gz包上传至/root目录下&#xff0c;将stack3_without_data.tar.gz包使用WinSCP上传至/opt目录下 vim run_yoga.sh #/bin/bash cd /root sudo apt-get update tar -xzv…

java面向对象总结

java面向对象篇到这里就已经结束了&#xff0c;有什么不懂的地方可以逐一进行重新观看。希望大家能够从入门到起飞。 Java面向对象基础篇综合训练&#xff08;附带全套源代码及逐语句分析&#xff09;-&#xff1e;基于javabeen Java面向对象进阶篇综合训练&#xff08;附带全…

如何跨专业通过软件设计师考试

链接&#xff1a;如何跨专业通过软件设计师-软件中级职称考试 (qq.com)

经济下行,企业还在“裁员至上”?

最近小红书、B站崩溃&#xff0c;又延伸到某云服务厂商问题频发&#xff0c;让人忍不住戏谑&#xff1a;“这算不算裁员裁到大动脉&#xff1f;” 在阿道看来&#xff0c;各大企业的裁员动作&#xff0c;绕不开的依旧是“人月神话”&#xff1a;盲目加人带来的是成本的倍增和效…