基于 多态 的职工管理系统(Staff Management System)

目录

一、管理系统需求

作用:管理公司内所有员工的信息

分类:要显示每位员工的编号、姓名、岗位与职责

具体实现的功能:

二、创建管理 类

三、各个接口函数

1、菜单展示功能

2、 选择功能

3、创建员工功能

        ①普通员工employee

        ②经理manager

        ③老板boss

4、添加功能

        4.1 添加员工

        4.2将添加的员工保存到文件中

         4.2.1写文件

         4.2.2读文件

5、显示员工

6、删除员工

6、修改员工

7、查找员工

8、排序员工

9、清空文件


一、管理系统需求

作用:管理公司内所有员工的信息


分类:要显示每位员工的编号、姓名、岗位与职责

普通员工:完成经理交给的任务

经理:完成老板交给的任务,并下发给员工

老板:管理公司所有事务


具体实现的功能:

①添加:实现批量添加职工功能,将职工信息(编号、姓名、职位)录入到文件中

②显示:显示当前公司内所有员工的信息

③删除:按照编号删除指定的员工

④修改:按照编号修改指定员工的信息

⑤查找:按照员工的姓名或编号

查找员工并显示其信息

⑥排序:按照员工编号进行升序或降序排列

⑦清空:清空文件中所有员工信息(需二次确认)

⑧退出:退出当前管理系统


二、创建管理 类

管理 类的作用:

①供用户选择的菜单界面

②对员工增删查改等的操作

③与数据文件的读写交互


首先需要头文件与源文件

并在文件中写入管理 类,并加上空的构造/析构函数

#pragma once
#include<iostream>
using namespace std;

class WorkerManager
{
public:
	// 构造函数
	WorkerManager();
	// 析构函数
	~WorkerManager();
};

并在源文件中空实现

#include<iostream>
using namespace std;
#include"workerManager.h"

	// 构造函数
WorkerManager::WorkerManager()
{

}
// 析构函数
WorkerManager::~WorkerManager()
{

}

三、各个接口函数

1、菜单展示功能

先在头文件的类中声明函数

	void Show_Menu();

 再在源文件中实现

void WorkerManager:: Show_Menu()
{
	cout << "***************************************" << endl;
	cout << "******** 欢迎使用教工管理系统!********" << endl;
	cout << "************ 1、添加员工 **************" << endl;
	cout << "************ 2、删除员工 **************" << endl;
	cout << "************ 3、显示员工 **************" << endl;
	cout << "************ 4、修改员工 **************" << endl;
	cout << "************ 5、查找员工 **************" << endl;
	cout << "************ 6、排序员工 **************" << endl;
	cout << "************ 7、清空员工 **************" << endl;
	cout << "************ 8、退出系统 **************" << endl;
	cout << "***************************************" << endl;
}

接下来我们回到主函数的源文件创建系统并尝试菜单功能

int main()
{
	WorkerManager WM;
	WM.Show_Menu();

	return 0;
}


2、 选择功能

在主函数中我们使用switch语句使得系统实现选择功能,并加上退出功能

int main()
{
	WorkerManager WM;
	int choice = 0;
	while (true)
	{
		WM.Show_Menu();
		cout << "请选择" << endl;
		cin >> choice;
		switch (choice)
		{
			case 1: // 添加
				break;
			case 2: // 删除
				break;
			case 3: // 显示
				break;
			case 4: // 修改
				break;
			case 5: // 查找
				break;
			case 6: // 排序
				break;
			case 7: // 清空
				break;
			case 0: // 退出
				WM.Exit_System();
				break;
			default:
				system("cls");
				break;
		}
	}
	return 0;
}
void WorkerManager:: Exit_System()
{
	cout << "退出系统!" << endl;
	exit(0);
}

3、创建员工功能

首先创建worker.h头文件,其内创建职工Worker基类,包含员工编号、姓名与岗位编号

// 员工抽象类_基类

class Worker
{
public:
	// 展示个人信息
	virtual void showInfo() = 0;
	// 获取个人岗位
	virtual string getDeptName() = 0;

	int m_id;		// 员工编号
	string m_name;// 员工姓名
	int m_Did;	// 所属部门编号
};

不需要具体实现,接下来,实现普通员工:

①普通员工employee

创建员工头文件employee.h源文件employee.cpp,并包含worker.h

头文件:子类employee继承父类Worker

class employee :public Worker
{
public:
	// 构造函数
	employee(int id, string name, int Did);
	// 展示个人信息
	virtual void showInfo();
	// 获取个人岗位
	virtual string getDeptName();
};

源文件:

    // 构造函数
employee::employee(int id, string name, int Did)
{
	this->m_id = id;
	this->m_name = name;
	this->m_Did = Did;
}
	// 展示个人信息
void employee:: showInfo()
{
	cout << "员工编号:" << this->m_id
		<< "\t员工姓名:" << this->m_name
		<< "\t员工岗位:" << this->getDeptName()
		<< "\t员工职责:完成经理安排的任务" << endl;
}
	// 获取个人岗位
string employee::getDeptName()
{
	return "普通员工";
}

main中测试:(先包含头文件和源文件)

int main()
{
	// test:

	Worker* worker = NULL;
	worker = new employee(22,"Joyce",1); 
	worker->showInfo();
	
	return 0;
}


②经理manager

同理:创建子类manager类,并继承父类Worker

头文件:

// 经理—子类
class manager :public Worker
{
public:
	// 构造函数
	manager(int id, string name, int Did);
	// 展示个人信息
	virtual void showInfo();
	// 获取个人岗位
	virtual string getDeptName();
};

源文件:

    // 构造函数
manager::manager(int id, string name, int Did)
{
	this->m_id = id;
	this->m_name = name;
	this->m_Did = Did;
}
	// 展示个人信息
void manager::showInfo()
{
	cout << "员工编号:" << this->m_id
		<< "\t员工姓名:" << this->m_name
		<< "\t员工岗位:" << this->getDeptName()
		<< "\t员工职责:完成老板安排的任务" << endl;
}
	// 获取个人岗位
string manager::getDeptName()
{
	return "经理";
}

③老板boss

同理:创建子类boss类,并继承父类Worker

头文件:

// 老板—子类
class boss :public Worker
{
public:
	// 构造函数
	boss(int id, string name, int Did);
	// 展示个人信息
	virtual void showInfo();
	// 获取个人岗位
	virtual string getDeptName();
};

源文件:

	// 构造函数
boss::boss(int id, string name, int Did)
{
	this->m_id = id;
	this->m_name = name;
	this->m_Did = Did;
}
	// 展示个人信息
void boss::showInfo()
{
	cout << "员工编号:" << this->m_id
		<< "\t员工姓名:" << this->m_name
		<< "\t员工岗位:" << this->getDeptName()
		<< "\t员工职责:安排所有任务" << endl;
}
	// 获取个人岗位
string boss::getDeptName()
{
	return "老板";
}

创建测试案例:(记得包含各个职位头文件)

int main()
{
	// test:
	Worker* worker1 = NULL;
	worker1 = new employee(1,"Joyce",1); 
	worker1->showInfo();
	delete worker1;

	Worker* worker2 = NULL;
	worker2 = new manager(2, "Nana", 2);
	worker2->showInfo();
	delete worker2;

	Worker* worker3 = NULL;
	worker3 = new boss(3, "Baby",3);
	worker3->showInfo();
	delete worker3;
	return 0;
}


4、添加功能

作用:批量添加员工,并保存到文件中


4.1 添加员工

首先,用户在添加员工时,会有不同的职位,如果我们把所有种类员工信息直接塞进一个数组中,存储将会困难,也可能会占用大量内存

因此,我们创建一个员工接着就创建一个指针,使该指针指向该员工的信息数据,并保存指针到一个数组中,这样我们在数组中就只有指针

而且,想要在程序中维护这个不定长度的指针,我们将数组创建到堆区,并使用Worker**的指针维护


代码:

首先在workerManager文件WorkerManager类中添加记录员工数量储存员工信息的指针这两个属性,并加入Add添加员工的接口函数

	// 记录员工数量
	int worker_num;

	// 储存员工的数组
	Worker** worker_array;

	// 添加员工功能
	void Add();

接着在workerManager的文件中的构造函数中初始化这两个属性

// 构造函数
WorkerManager::WorkerManager()
{
	// 初始化属性
	this->worker_num = 0;
	this->worker_array = NULL;
}

实现Add添加员工函数 

void WorkerManager::Add()
{
	cout << "请输入要添加员工的个数:"<< endl;
	int Add_num = 0;
	cin >> Add_num;
	if (Add_num > 0)
	{
		// 计算添加后员工的总数
		int newSize = this->worker_num + Add_num;
		
		// 开辟新空间
		Worker** newSpace = new Worker * [newSize];

		// 将原来空间的数据拷贝到新空间
		if (this->worker_array != NULL)
		{
			for (int i = 0; i < this->worker_num; i++)
			{
				newSpace[i] = this->worker_array[i];
			}
		}
		// 将新数据添加至新空间的后面
		for (int j = 0; j < Add_num; j++)
		{
			int id;
			string name;
			int Did;
			cout << "请输入第" << j + 1 << "个新员工的编号" << endl;
			while (true)
			{
				cin >> id;
				int ret = this->worker_isExit(id);
				if (ret != -1)
				{
					cout << "用户编号已存在!请重新输入:" << endl;
				}
				else
				{
					break;
				}
			}
			cout << "请输入第" << j + 1 << "个新员工的姓名" << endl;
			cin >> name;
			cout << "请输入第" << j + 1 << "个新员工的部门:" << 
				"1、普通员工 "
				"2、经理 "
				"3、老板"<<endl;
			cin >> Did;

			// 根据部门编号创建不同的职位
			Worker* worker = NULL;
			switch (Did)
			{
				case 1:
					worker = new employee(id, name, Did);
					break;
				case 2:
					worker = new manager(id, name, Did);
					break;
				case 3:
					worker = new boss(id, name, Did);
					break;
				default:
					cout << "输入错误" << endl;
					break;
			}
			// 将创建的员工指针,保存至数组中
			newSpace[this->worker_num + j] = worker;
		}
		// 释放原有数组的空间
		delete[] this->worker_array;
		// 更新新空间的指向
		this->worker_array = newSpace;
		// 更新新空间的人数
		this->worker_num = newSize;
		cout << "成功添加" << Add_num << "名新员工!" << endl;
		Sleep(1000); // 暂停1000毫秒
		system("pause");// 按任意键继续
		system("cls"); // 清屏
	}
	else
	{
		cout << "输入错误!" << endl;
	}
}

然后,记得堆区手动开辟的数据要手动释放,析构函数

// 析构函数
WorkerManager::~WorkerManager()
{
	if (this->worker_array != NULL)
	{
		delete[]this->worker_array;
		this->worker_array = NULL;
	}
}

最后在main函数加入Add函数后进行测试


4.2将添加的员工保存到文件中

添加头文件<fstream>后就可以直接开始


 4.2.1写文件

首先在主体函数中添加保存数据到文件的save函数

然后在源文件中实现:

void WorkerManager::save()
{
	ofstream	ofs;
	ofs.open("WorkerFile.txt", ios::out);
	for (int i = 0; i < this->worker_num; i++)
	{
		ofs << this->worker_array[i]->m_id<<" "
			<< this->worker_array[i]->m_name << " "
			<< this->worker_array[i]->m_Did << endl;
	}
	ofs.close();
}

最后在Add函数中调用即可


 4.2.2读文件

作用:将文件中的内容读取到程序中

上面实现了将添加的员工保存到文件中,但是文件中的员工信息我们还不能读取到程序中


而文件实际有3种状态:

①第一次使用程序,文件未创建不存在

②文件存在,但数据被用户清空

③文件存在,保存有员工的数据


我们在workerManager头文件中添加新的变量:bool m_FileIsEmpty;来判断文件是否为空

 然后修改源文件中构造函数

①文件不存在

// 构造函数
WorkerManager::WorkerManager()
{
	// 1、文件不存在
	ifstream ifs;
	ifs.open("FILENAME", ios::in);

	if (!ifs.is_open())
	{
		cout << "文件不存在!" << endl;
			// 初始化属性
		this->worker_num = 0;
		this->worker_array = NULL;
		this->m_FileIsEmpty = true;// 初始为空
	}
}

②文件存在,但无数据

我们将文件取1个字符到一个字符变量里,然后使用函数eof()判断文件是否为空,若函数为真则为空(若无数据,文件里最后一个字符将是EOF文件结束标志,上面提取了就没了为空)

	// 2、文件存在,无数据
	char ch = 0;
	ifs >> ch; // 取1个字符
	if (ifs.eof())
	{
		cout << "文件为空!" << endl;
			// 初始化属性
		this->worker_num = 0;
		this->worker_array = NULL;
		this->m_FileIsEmpty = true;// 初始为空
		ifs.close();
	}

③文件存在有数据

首先我们增加一个统计文件中有多少人函数get_WorkerNum()

 在源文件中实现

int WorkerManager::get_WorkerNum()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);
	int id;
	string name;
	int Did;
	int number = 0;
	while (ifs >> id && ifs >> name && ifs >> Did)// 读取一行
	{
		number++;
	}
	return number;
}

 然后实现一个初始化员工的函数Init()

void WorkerManager::Init()
{
	ifstream ifs;
	ifs.open(FILENAME, ios::in);
	int id;
	string name;
	int Did;
	int number = 0;

	while (ifs >> id && ifs >> name && ifs >> Did)
	{
		Worker* worker = NULL;
		// 根据不同的部门创建不同的对象
		if (Did == 1)
		{
			worker = new employee(id,name,Did);
		}
		else if (Did == 2)
		{
			worker = new manager(id, name, Did);
		}
		else
		{
			worker = new boss(id, name, Did);
		}
		this->worker_array[number] = worker;// 将对象放在数组中维护
		number++;
	}
	ifs.close();
}

最后补全③

首先获取员工的个数,然后根据个数创建空间,然后初始化空间

	// 3、文件存在,有数据
	// 先获取员工的个数
	int num = get_WorkerNum();
	cout << "共有" << num << "个员工" << endl;
	this->worker_num = num;

	// 根据个数创建空间
	this->worker_array = new Worker * [this->worker_num];
	// 初始化员工
	this->Init();

加上测试

// 测试:
	for (int i=0; i < this->worker_num; i++)
	{
		cout << "员工编号:" << this->worker_array[i]->m_id <<
			"\t员工名字:" << this->worker_array[i]->m_name <<
			"\t部门为" << this->worker_array[i]->m_Did << endl;
	}

 5、显示员工

直接调用showInfo()函数即可


分为3种情况:

①文件为空,没有员工②文件存在,没有员工③文件存在,有员工

①和②可以合并


首先在workerManager头文件中创建show_worker()函数

然后在源文件中实现

void WorkerManager::show_worker()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件为空或不存在!" << endl;
		Sleep(1000);
	}
	else
	{
		for (int i = 0; i < this->get_WorkerNum(); i++)
		{
			this->worker_array[i]->showInfo();
			Sleep(50); 
		}
	}	
		system("pause");// 按任意键继续
		system("cls"); // 清屏
}

6、删除员工

分为3步,首先判断员工是否存在,存在返回员工编号,然后删除员工编号的数据


首先创建判断员工是否存在worker_isExit()函数删除员工函数del_worker()

先实现worker_isExit()函数

int WorkerManager::worker_isExit(int id)
{
	for (int i = 0; i < this->worker_num; i++)
	{
		if (this->worker_array[i]->m_id == id)
			return i;
	}
	return -1;
}

然后实现del_worker()函数:从要删除的数据开始从后往前覆盖数据即可

void WorkerManager::del_worker()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件为空!" << endl;
	}
	else
	{
		cout << "请输入要删除的员工id:" << endl;
		int input = 0;
		cin >> input;
		int ret = worker_isExit(input);
		if (ret == -1)
		{
			cout << "删除失败,员工不存在!" << endl;
		}
		else
		{
			if (input == this->worker_num) // 如果输入的是末尾员工的id,数组直接 - 1即可
			{
				this->worker_num--;
			}
			else
			{
                   // 数据前移,数组中后一个数据覆盖到前一个
				for (int i = ret; i < this->worker_num - 1; i++)
				{
					this->worker_array[i] = this->worker_array[i + 1];
				}
				this->worker_num--;
			}
			this->save();
			cout << "删除成功!" << endl;
		}
	}
	Sleep(1000);
	system("pause");// 按任意键继续
	system("cls"); // 清屏
}

6、修改员工

worker_Manager头文件创建修改员工函数mod_worker();


输入要修改的员工编号,存在则先delete掉那个位置的员工数据,然后重新new一个worker,再写入其编号姓名与部门,最后把worker赋值给刚才delete掉的那个位置

void WorkerManager::mod_worker()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或为空!" << endl;
	}
	else
	{
		cout << "请输入要修改的员工id:" << endl;
		int input = 0;
		cin >> input;
		int ret = worker_isExit(input);
		if (ret == -1)
		{
			cout << "修改失败,员工不存在!" << endl;
		}
		else
		{
			delete this->worker_array[ret];
			int id = 1;
			string name;
			int Did;
			cout << "已查找到,请输入员工新的编号" << endl;
			while (true)
			{
				cin >> id;
				int ret = this->worker_isExit(id);
				if (ret != -1)
				{
					cout << "用户编号已存在!请重新输入:" << endl;
				}
				else
				{
					break;
				}
			}
			cout << "请输入员工新的姓名" << endl;
			cin >> name;
			cout << "请输入员工新的部门:" <<
				"1、普通员工 "
				"2、经理 "
				"3、老板" << endl;
			cin >> Did;

			// 根据部门编号创建不同的职位
			Worker* worker = NULL;
			switch (Did)
			{
				case 1:
					worker = new employee(id, name, Did);
					break;
				case 2:
					worker = new manager(id, name, Did);
					break;
				case 3:
					worker = new boss(id, name, Did);
					break;
				default:
					cout << "输入错误" << endl;
					break;
			}
			this->worker_array[ret] = worker;
			cout << "修改成功!" << endl;
			this->save();
		}
	}
	Sleep(1000);
	system("pause");
	system("cls");
}

7、查找员工

有2种方式:①编号查找②姓名查找

也就是分别对比编号姓名是否相等即可


首先创建查找员工函数find_worker();

 然后在源文件中实现:

        比对信息很简单,只要将输入的内容遍历与文件中的信息对比即可,有则输出信息,没有则输出查无此人。

        同时,我们创建是否找到员工变量woreker_isFind;初始值即为false,找到员工改为true,遍历完后再根据true或者false确定是否输出查无此人。

void WorkerManager::find_worker()
{
	cout << "请输入查找模式:" << endl;
	cout << "1、编号查找	2、姓名查找	" << endl;
	int input = 0;
	cin >> input;
	// 1、编号查找
	if (input == 1)
	{
		cout << "请输入要查找人的编号:" << endl;
		int id = 0;
		cin >> id;
		int ret = this->worker_isExit(id);
		if (ret == -1)
		{
			cout << "查无此人!" << endl;
		}
		else
		{
			cout << "已查到编号为 " << id << " 的员工,信息如下:" << endl;
			this->worker_array[ret]->showInfo();
		}
	}
	// 2、姓名查找
	else if (input == 2)	
	{
		cout << "请输入要查找人的姓名:" << endl;
		string name;
		// 创建是否找到员工的变量,找到返回true,否则一直是false
		bool worker_isFind = false;
		cin >> name;
		for (int i = 0; i < this->worker_num; i++)
		{
			if (name == this->worker_array[i]->m_name)
			{
				cout << "已查到姓名为 " << name << " 的员工,信息如下:" << endl;
				this->worker_array[i]->showInfo();
				worker_isFind = true;
			}
		}
		if (worker_isFind == false)// 根据是否找到员工(即是否是false),输出查无此人
		{
			cout << "查无此人!" << endl;
		}
	}
	else
	{
		cout << "输入错误!" << endl;
		return;
	}
	Sleep(1000);
	system("pause");
	system("cls");
}

8、排序员工

2种方法:升序排列or降序排列

我们使用选择排序

void WorkerManager::sort_worker()
{
	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或为空!" << endl;
		system("pause");
		system("cls");
	}
	else
	{
		cout << "请输入排序方式:" << endl;
		cout << "1、升序排序    2、降序排序 " << endl;
		int input = 0;
		cin >> input;
		int minORmax = 0;

		for (int i = 0; i < this->worker_num; i++)
		{
			int minORmax = i; // 设定最小值或最大值
			for (int j = i + 1; j < this->worker_num; j++)
			{
				if (input == 1) // 升序
				{
					if (this->worker_array[minORmax]->m_id > this->worker_array[j]->m_id)
					{	// 如果我们设定的最小值比数组中某个数还小
						minORmax = j; //交换下标
					}
				}
				else // 降序
				{
					if (this->worker_array[minORmax]->m_id < this->worker_array[j]->m_id)
					{	// 如果我们设定的最小值比数组中某个数还大
						minORmax = j;
					}
				}
			}
			if (i != minORmax) // 下标有交换,则和原来的i不同,就可以进行数据的交换
			{
				swap(this->worker_array[minORmax], this->worker_array[i]);
			}
		}
		this->save();
		cout << "排序成功!" << endl;
		cout << "排序后结果为:" << endl;
		this->show_worker();
	}
}

9、清空文件

先创建销毁函数

源文件中实现:

清空文件,再销毁数组

销毁数组时,先销毁每个元素,再销毁整个数组。

void WorkerManager::cleam_worker()
{

	if (this->m_FileIsEmpty)
	{
		cout << "文件不存在或为空!" << endl;
		system("pause");
		system("cls");
	}
	else
	{
		cout << "确认清空文件?" << endl;
		cout << "1、确定   2、返回" << endl;
		int input = 0;
		cin >> input;
		if (input == 1)
		{
			// 1、先清空文件
			// 直接使用文件打开方式的 trunc:文件存在先删除再创建
			ofstream ofs(FILENAME, ios::trunc);
			ofs.close();

			// 2、再清空数组
			if (this->worker_array != NULL)
			{
				// 2.1先删除堆区每个员工对象(数组每个元素)
				for (int i = 0; i < this->worker_num; i++)
				{
					delete this->worker_array[i];
					this->worker_array[i] = NULL;
				}
			}
			// 2.2再清空数组
			delete[]this->worker_array;
			this->worker_array = NULL;
			this->worker_num = 0;
			this->m_FileIsEmpty = true; // 文件为空的标志
		}
		cout << "清空成功!" << endl;
		system("pause");
		system("cls");
	}
}

至此完成全部功能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么批量把heic格式转化jpg,3招快速解决

怎么批量把heic格式转化jpg&#xff1f;heic是一种新型的图像文件格式&#xff0c;是苹果独家搞出来的一个图片格式&#xff0c;它小巧玲珑&#xff0c;而且图像质量超好&#xff0c;专门给iOS11系统用户用的。这种格式比老JPEG更厉害&#xff0c;不仅图片质量好&#xff0c;而…

【网络原理】应用层协议 与 传输层协议

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; 目 录 &#x1f3c9;一. 应用层协议⚾️二. 传输层协议&#x1f452;1. UDP 协议&#x1f302;2. 校验和&#x1f453;3. TCP 协议 &#x1f3c9;一. 应用层协议 我们自己写的应用…

Bitmap 实现当前在线用户数量

Bitmap是什么&#xff1f; Bitmap是Redis中的一种数据结构&#xff0c;它是一个类似于位数组的数据结构&#xff0c;用于处理位数据。在Redis中&#xff0c;Bitmap是使用字符串来存储的&#xff0c;一个Byte可以存储8个二进制位&#xff0c;一个字符串可以存储232个二进制位&a…

【CocosCreator入门】CocosCreator组件 | ProgressBar(进度条)组件

Cocos Creator 是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中的ProgressBar组件是一种用于实现进度条效果的重要组件。它可以让我们在游戏中展示各种进度条效果&#xff0c;例如加载进度条、血条等。 目录 一、组件介绍 二、组件属性 三、脚本…

12. 图的进阶

12. 图的进阶 12.1 有向图 在实际生活中&#xff0c;很多应用相关的图都是有方向性的&#xff0c;最直观的就是网络&#xff0c;可以从A页面通过链接跳转到B页面&#xff0c;那么a和b连接的方向是a->b,但不能说是b->a,此时我们就需要使用有向图来解决这一类问题&#x…

【jvm系列-09】垃圾回收底层原理和算法以及JProfiler的基本使用

JVM系列整体栏目 内容链接地址【一】初识虚拟机与java虚拟机https://blog.csdn.net/zhenghuishengq/article/details/129544460【二】jvm的类加载子系统以及jclasslib的基本使用https://blog.csdn.net/zhenghuishengq/article/details/129610963【三】运行时私有区域之虚拟机栈…

为什么许多人吐槽C++11,那些语法值得我们学习呢?

致前行的人&#xff1a; 人生像攀登一座山&#xff0c;而找寻出路&#xff0c;却是一种学习的过程&#xff0c;我们应当在这过程中&#xff0c;学习稳定冷静&#xff0c;学习如何从慌乱中找到生机。 目录 1.C11简介 2.统一的列表初始化 2.1 &#xff5b;&#xff5d;初始化 …

git 常用命令及遇到问题

自己没事&#xff0c;把git常用命令做个记录总结。方便自己和初学者查看&#xff0c;本文针对初学者&#xff0c;如果你已经是工作多年高手&#xff0c;请跳过。 git的几个区认识&#xff0c;分别为工作区&#xff0c;缓存区&#xff0c;版本库。 工作区&#xff1a;包含.git…

【Unity VR开发】结合VRTK4.0:添加碰撞忽略器

语录&#xff1a; 最远的旅行&#xff0c;是从自己的身体到自己的心&#xff0c;是从一个人的心到另一个人的心。坚强不是面对悲伤不流一滴泪&#xff0c;而是擦干眼泪后微笑面对以后的生活。 前言&#xff1a; 模块化提供了一种允许两个或者多个对象忽略彼此碰撞的方法&#x…

揭秘移动云大会展区前沿科技

2023年4月25日-26日 我们苏州金鸡湖国际会议中心见&#xff01; 1场重磅主论坛、10场分论坛、2600㎡展区 数字中国新未来 尽在2023移动云大会 2023移动云大会设有中国移动和合作伙伴两大展区&#xff0c;联合40余家优质合作伙伴&#xff0c;全方位展示移动云在自主能力、行…

vue yarn npm

2016年左右 &#xff0c;facebook针对npm包管理工具存在的性能问题进行了针对性开发并发布了yarn新的node包开发管理工具&#xff0c;具体对比&#xff0c;同学们自行网上搜索资料对比。 配置 1、先下载好NodeJS&#xff0c;然后输入如下命令安装yarn npm install -g yarn 2、…

如何微调Segment Anything Model

文章目录 什么是SAM&#xff1f;什么是模型微调&#xff1f;为什么要微调模型&#xff1f;如何微调 Segment Anything 模型背景与架构创建自定义数据集输入数据预处理训练设置循环训练保存检查点并从中启动模型 下游应用程序的微调 随着 Meta 上周发布的 Segment Anything Mode…

线程等待其他线程执行同步类CountDownLatch

文章目录 前言核心原理源码解析同步源码分析await源码分析countDown源码分析 实战演示1、创建演示代码2、创建测试用例3、测试结果演示 写在最后 前言 大家都知道多线程在我们实际编码过程中运用很多&#xff0c;很多情况我们需要靠多线程来提升系统性能。但是有些时候我们需要…

C语言开发环境搭建及调试

C简介 可移植 标准C C/C &#xff08;系统硬件操作的接口&#xff0c;windows&#xff0c;Linux不一样&#xff09; 跨平台 Java Python 下载 去官网选择Visual Studio 2019下载 安装过程中勾选使用C的桌面开发 安装好之后点击创建新项目——空项目 位置最好放在根目录下&…

【vue2】近期bug收集与整理02

⭐【前言】 在使用vue2构建页面时候&#xff0c;博主遇到的问题难点以及最终的解决方案。 &#x1f973;博主&#xff1a;初映CY的前说(前端领域) &#x1f918;本文核心&#xff1a;博主遇到的问题与解决思路 目录 ⭐数据枚举文件的使用⭐elementUI中分页组件使用的注意事项⭐…

OpenAI-ChatGPT最新官方接口《从0到1生产最佳实例》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(十一)(附源码)

Production Best Practices 生产最佳实例 前言Introduction 导言Setting up your organization 设置您的组织Managing billing limits 管理计费限额API keys API密钥Staging accounts 演示账户 Building your prototype 构建您的原型Additional tips 其它技巧 Techniques for i…

C++函数重载

目录 函数重载函数重载是怎样实现的 函数重载 函数重载&#xff1a;是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同&#xff0c;常用来处理实现功能类似数据类型不同的…

找PPT模板就上这5个网站~

分享几个可以永久免费下载PPT模板、素材的网站&#xff0c;上万个模板随便下载&#xff0c;赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYxMjky 网站素材非常全面&#xff0c;主要以设计类素材为主&#xff0c;办公类素材也很多&#x…

Spring MVC 接收 json 和返回 json (14)

目录 总入口 测试case 源码分析 1. 针对RequestBody的参数解析 2. 针对 ResponseBody 的返回值处理 总入口 通过上一篇Spring MVC 参数解析&#xff08;13&#xff09;_chen_yao_kerr的博客-CSDN博客的说明&#xff0c;相信大家对Sping MVC的参数解析有了一定的了解&…

8. 优先队列

8. 优先队列 普通的队列是一种先进先出的数据结构&#xff0c;元素在队列尾追加&#xff0c;而从队列头删除。在某些情况下&#xff0c;我们可能需要找出队列中的最大值或者最小值&#xff0c;例如使用一个队列保存计算机的任务&#xff0c;一般情况下计算机的任务都是有优先级…