C/C++ 实战项目 —— 职工管理系统(上)

在这里插入图片描述

在这里插入图片描述

🎁个人主页:工藤新一¹

🔍系列专栏:C++面向对象(类和对象篇)

​ 🌟心中的天空之城,终会照亮我前方的路

🎉欢迎大家点赞👍评论📝收藏⭐文章

C++ 项目 — 职工管理系统

一、项目日志

职工管理系统可以用来管理公司内所有员工的信息

本教程主要利用 C++ 来实现一个基于 多态 的职工管理系统

公司中职工分为三类:普通员工,经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责。

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

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

  • 老板的职责: 管理公司所有的事务

管理系统中需要实现的功能如下:

  • **退出管理程序:**退出当前管理系统

  • **增加职工信息:**实现批量添加职工功能,将信息录入文件中,职工信息为职工编号、姓名、部门编号

  • 显示职工信息, 显示公司内部所有职工的信息

  • 删除离职职工: 按照编号删除指定的职工

  • 修改职工信息: 按照编号修改职工的个人信息

  • 查找职工信息: 按照职工的编号或者职工的姓名进行查找相关的人员信息

  • 按照编号排序: 按照职工编号进行排序,排序规则由用户指定

  • 清空所有的文档: 清空文件中记录所有职工的信息,清空前需要再次确认,防止误删。

其中联系各项功能的纽带:我们称之为接口


二、创建管理类

2.1功能描述

管理类负责功能如下:

  • 与用户直接沟通的菜单页面
  • 提供对职工进行增删改查操作的接口
  • 与文件进行交互

2.2头文件实现

WorkerManager.h设计管理类

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

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

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

2.3源文件实现

WorkerManager.cpp构造函数、析构函数补全

C++
	#include"WorkerManager.h"

	WorkerManager::WorkerManager(){}

	WorkerManager::~WorkerManager(){}

至此职工管理类创建完毕。


三、菜单功能

  • 功能描述:与用户沟通、交互的界面

3.1添加成员函数

在管理类WorkerManager.h中增添成员函数 void Shou_Menu();

在这里插入图片描述


3.2菜单功能的实现

在管理类WorkerManager.cpp中实现成员函数 Shou_Menu()

C++
	void WorkerManager::Shou_Menu()
	{
		cout<< "******************************************" << endl;
		cout<< "********   欢迎使用职工管理系统    *******" << endl;
		cout<< "***********   0. 退出管理系统   **********" << endl;
		cout<< "***********   1. 添加职工信息   **********" << endl;
		cout<< "***********   2. 显示职工信息   **********" << endl;
		cout<< "***********   3. 删除职工信息   **********" << endl;
		cout<< "***********   4. 修改职工信息   **********" << endl;
		cout<< "***********   5. 查找职工信息   **********" << endl;
		cout<< "***********   6. 按照编号排序   **********" << endl;
		cout<< "***********   7. 清空所有文档   **********" << endl;
		cout<< "******************************************" << endl;
		cout << endl;
	}

3.3测试菜单功能

职工管理系统 SMSystem.cpp 中测试菜单功能

C++
    #include"WorkerManager.h"

	int main()
	{
		//实例化一个工作管理对象
		WorkerManager wm;

		wm.Shou_Menu();
    
		return 0;
	}

运行效果如图:

在这里插入图片描述


四、退出功能

4.1提供功能接口

main函数提供分支选择,提供功能接口

C++
    
int main()
{
	//实例化一个工作管理对象
	WorkerManager wm;

	int choice = 0;//接收用户的选项
	while (true)
	{
		//展示菜单
		wm.Shou_Menu();
		cout<<"请输入您的选择: " << endl;
		cin >> choice;
		
		//使用 switch语句 去承接(处理)用户不同地选择
		switch (choice)
		{
		case 0://退出系统
			break;
		case 1://添加职工
			break;
		case 2://显示职工
			break;
		case 3://删除职工
			break;
		case 4://修改职工
			break;
		case 5://查找职工
			break;
		case 6://排序职工
			break;
		case 7://清空文件
			break;
		default:
			system("cls");
			break;
		}
	}
	
	system("pause");
	return 0;
}

4.2实现退出功能

WorkerManager.h 提供退出系统的成员函数 void ExitSystem();

WorkerManager.cpp 提供具体功能的实现

C++
	void WorkerManager::ExitSystem()
	{
		cout << "欢迎下次使用" << endl;
		system("pause");
		exit(1);
	}

4.3测试功能

main函数 分支为 0 的选项中,调用退出程序地接口

在这里插入图片描述


五、职工类(抽象类)

5.1创建职工抽象类

  • 抽象基类(多态),在其他文件中被继承

职工的分类为:普通员工、经理、老板

将三种职工抽象到一个类(work)中,利用多态管理不同职工种类(利用多态,显示不同职工内容)

职工的属性为:职工编号,职工姓名,职工所在的部门编号

职工的行为:岗位职责信息描述,获取岗位名称

头文件夹下创建 Worker.h 并添加如下代码:

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

//职工抽象类  -  抽象基类,在其他文件中被继承
class Worker
{
public:

	//显示个人信息 - 在抽象类中不做任何实现
	virtual void ShowInfo() = 0;//直接在函数体内 cout 输出信息

	//获取岗位名称 - 在抽象类中不做任何实现
	virtual string GetDepName() = 0;//返回岗位名称(字符串)

	int m_id;//职工编号 
	string m_Name;//职工姓名 
	int m_DeptId;//职工所处部门的编号 
};

5.2创建普通职工类

  • 普通员工类继承职工抽象类并重写父类中的纯虚函数(子类重写父类中的纯虚函数)

在**头文件 **和 源文件中分别加入 Employee.hEmployee.cpp

Employee.h头文件中:

#pragma once
#include"Worker.h" 

//继承抽象类 Worker
class Employee : public Worker
{
public:
    
	//构造函数 - 初始化成员变量
	Employee(int id, string name, int did);

	//子类中重写父类中的纯虚函数(virtual 在子类中可删可不删)
	virtual void ShowInfo();

    //子类中重写父类中的纯虚函数(virtual 在子类中可删可不删)
	virtual string GetDepName();
};

Employee.cpp头文件中:

#pragma once
#include"Employee.h" 

Employee::Employee(int id, string name, int did)
{
	m_id = id;
	m_Name = name;
	m_DeptId = did;
}

void Employee::ShowInfo()
{
	cout << "职工编号:" << this->m_id
		<< "\t 职工姓名:" << this->m_Name
		<< "\t 岗位职责:完成经理交给的任务。" << endl;
}

string Employee::GetDepName()
{
    //强制转换为 C++ 字符串
	return string("员工");
}

5.3创建经理类

同 员工类 类似,经理类继承职工抽象类,并重写父类中的纯虚函数

在**头文件 **和 源文件中分别加入 Manager.hManager.cpp

Manager.h 中代码如下:

#pragma once
#include"Worker.h" 

class Manager : public Worker
{
public:

	Manager(int id, string name, int did);

	virtual void ShowInfo();

	virtual string GetDepName();
};

Manager.cpp 中代码如下:

#include"MAnager.h" 

Manager::Manager(int id, string name, int did)
{
	this->m_id = id;
	this->m_Name = name;
	this->m_DeptId = did;
}

void Manager::ShowInfo()
{
	cout << "职工编号:" << this->m_id
		<< "\t 职工姓名:" << this->m_Name
		<< "\t 岗位职责:完成老板交给的任务,并下发任务给员工。" << endl;
}

string Manager::GetDepName()
{
    //强制转换为 C++ 字符串
	return string("经理");
}

5.4创建 Boss 类

Boss类继承职工抽象类,并重写父类中的纯虚函数

在**头文件 **和 源文件中分别加入 Boss.hBoss.cpp

Boss.h

#pragma once
#include"Worker.h" 

class Boss : public Worker
{
	Boss(int id, string name, int did);

	virtual void ShowInfo() = 0;

	virtual string GetDeptName() = 0;
};

Boss.cpp

#include"Boss.h" 

Boss::Boss(int id, string name, int did)
{
	m_id = id;
	m_Name = name;
	m_DeptId = did;
}

void Boss::ShowInfo()
{
	cout << "职工编号:" << this->m_id
		<< "\t 职工姓名:" << this->m_Name
		<< "\t 岗位职责:发任务给所有职工" << endl;
}

string  Boss::GetDeptName()
{
    //强制转换为 C++ 字符串
	return string("Boss");
}

5.5测试多态

在职工管理系统 SMSytem.cpp 中添加测试函数,并且运行能够产生多态

#include"WorkerManager.h"

#include"Worker.h"
#include"Manager.h"
#include"Employee.h"
#include"Boss.h"

void test()
{
    //创建抽象类指针(父类指针/引用)指向子类对象
	Worker* worker1 = NULL;
	worker1 = new Boss(1, "啦啦啦", 1);
	worker1->ShowInfo();
	delete worker1;

    //创建抽象类指针(父类指针/引用)指向子类对象
	Worker* worker2 = NULL;
	worker2 = new Manager(2, "呦呦呦", 2);
	worker2->ShowInfo();
	delete worker2;

    //创建抽象类指针(父类指针/引用)指向子类对象
	Worker* worker3 = NULL;
	worker3 = new Employee(3, "Gont", 3);
	worker3->ShowInfo();
	delete worker3;
}
int main(){	
    //测试代码
	test();

	system("pause");
	return 0;
}

在这里插入图片描述


六、添加职工

  • 功能描述:批量添加职工,并且存放到文件中

6.1功能分析

分析:

用户在批量创建时,可能会创建不同种类的职工

如果想存放不同种类的职工,可以将所有职工的指针维护到一个数组中(指针数组)

其中,指针数组必定是一个不定长度的数组,因此可以将数组开辟到堆区,使用 Worker**指针维护

在这里插入图片描述


6.2功能实现

WorkerManager.h 头文件中,添加成员属性

C++
    //记录文件中的人员数量
	int m_EmpNum;

	//员工数组的指针 - 维护在堆区开辟的子类对象
	Worker** m_EmpArr;

在 **WorkerManager ** 构造函数中初始化属性

C++
	WorkerManager::WorkerManager()
	{
		//初始化人数
		this->m_EmpNum = 0;

		//初始化数组
		this->m_EmpArr = NULL;
	}

WorkerManager.h 头文件中添加成员函数

C++
	//增加职工
    void Add_Emp();

WorkerManager.cpp

a.在堆区开辟大小为 newSize 的新空间,并使用 Worker** 指针维护这段空间

在这里插入图片描述

C++
	//添加 - 计算新添加后空间的大小(原来人数 + 添加人数) 
	int newSize = this->m_EmpNum + addNum;

	//在堆区开辟大小为 newSize 的新空间,并使用 Worker** 指针维护这段空间
	Worker** newSpace = new Worker* [newSize];

b.拷贝旧数据、存储新数据、释放旧空间

C++
    // 将原来空间下的数据, 拷贝到新空间
	if (this->m_EmpArr != NULL)
	{
		for (int i = 0; i < this->m_EmpNum; ++i)
		{
			newSpace[i] = this->m_EmpArr[i];
		}
	}

c.父类指针指向子类对象

C++
	//根据用户不同的创建,我们需要 new 出不同的对象 - 父类指针指向子类对象
	Worker* worker = NULL;
	switch (DeSelect)
	{
	case 1:
		worker = new Employee(id, name, 1);
		break;
	case 2:
		worker = new Manager(id, name, 2);
		break;
	case 3:
		worker = new Boss(id, name, 3);
		break;
	default:
		break;
	}

	//将创建的职工指针,存储到数组中 - 以 m_EmpNum 位置为起始点,开始存放 worker 指针
	newSpace[this->m_EmpNum + i] = worker;

	//释放原有的空间(释放旧空间)
	delete[] this->m_EmpArr;

d.更新职工数组指针的指向 + 更新员工人数

C++
    //将新空间的地址赋值给成员(指针)变量 - 更改员工数组指针的指向
	this->m_EmpArr = newSpace;

	//更新员工人数
	this->m_EmpNum = newSize;

e.调用析构函数,回收、释放堆区数据

C++
    //析构函数中释放堆区数据
	WorkerManager::~WorkerManager()
	{
		if (this->m_EmpArr != NULL)
		{
			delete[] this->m_EmpArr;
			this->m_EmpArr = NULL;
		}
	}

//添加职工
void WorkerManager::Add_Emp()
{
	cout<< "请输入添加职工数量: " << endl;
	
	int addNum = 0;cin >> addNum;

	if (addNum > 0)
	{
		//添加 - 计算新添加后空间的大小(原来人数 + 添加人数) 
		int newSize = this->m_EmpNum + addNum;

		//在堆区开辟大小为 newSize 的新空间,并使用 Worker** 指针维护这段空间
		Worker** newSpace = new Worker* [newSize];

		// 将原来空间下的数据, 拷贝到新空间
		if (this->m_EmpArr != NULL)
		{
			for (int i = 0; i < this->m_EmpNum; ++i)
			{
				newSpace[i] = this->m_EmpArr[i];
			}
		}
/*
copy(this->m_EmpArr, this->m_EmpArr + this->m_EmpNum, newSpace);

模板函数 copy - 复制数组中的元素
this->m_EmpArr:这是源数组的起始指针,指向要复制的数组的第一个元素。
this->m_EmpArr + this->m_EmpNum:这是源数组的结束指针,指向要复制的数组的最后一个元素之后的位置。m_EmpNum 是数组中的元素数量。
newSpace:这是目标数组的起始指针,指向新分配的数组的第一个元素。

std::copy 函数会从 m_EmpArr 开始,复制 m_EmpNum 个元素到 newSpace 中。
它会逐个复制元素,直到达到 m_EmpArr + m_EmpNum。


示例
假设 m_EmpArr 是一个包含三个元素的数组:
m_EmpArr:  [Worker1, Worker2, Worker3]
newSpace 是一个新分配的数组,大小为 newSize:
newSpace:  [nullptr, nullptr, nullptr, ...]
执行 std::copy 后,newSpace 将包含从 m_EmpArr 复制的元素:
newSpace:  [Worker1, Worker2, Worker3, ...]
*/

		//批量添加新数据 
		for (int i = 0; i < addNum; i++)
		{
			int id;//职工编号
			string name;//职工姓名
			int DeSelect;//部门选择 

			cout << "请输入第 " << i + 1 << " 位员工的职工编号:" << endl;
			cin >> id;

			cout << "请输入第 " << i + 1 << " 位员工的姓名:" << endl;
			cin >> name;

			cout << "请选择该职工岗位:" << endl;
			cout << " 1、普通职工 " << endl;
			cout << " 2、经理 " << endl;
			cout << " 3、Boss " << endl;
			cin >> DeSelect;

			//根据用户不同的创建,我们需要 new 出不同的对象 - 父类指针指向子类对象
			Worker* worker = NULL;
			switch (DeSelect)
			{
			case 1:
				worker = new Employee(id, name, 1);
				break;
			case 2:
				worker = new Manager(id, name, 2);
				break;
			case 3:
				worker = new Boss(id, name, 3);
				break;
			default:
				break;
			}

			//将创建的职工指针,存储到数组中 - 以 m_EmpNum 位置为起始点,开始存放 worker 指针
			newSpace[this->m_EmpNum + i] = worker;
		}

		//释放原有的空间(释放旧空间)
		delete[] this->m_EmpArr;

		//将新空间的地址赋值给成员(指针)变量 - 更改员工数组指针的指向
		this->m_EmpArr = newSpace;

		//更新员工人数
		this->m_EmpNum = newSize;

		//提示添加成功
		cout << "成功添加" << addNum << "位职工" << endl;
	}
	else 
	{
		cout << "输入数据有误" << endl;
	}

	//按任意键后,清屏回到上级目录
	system("pause");//等待用户输入任意键
	system("cls");//清屏
}

//析构函数中释放堆区数据
WorkerManager::~WorkerManager()
{
	if (this->m_EmpArr != NULL)
	{
		delete[] this->m_EmpArr;
		this->m_EmpArr = NULL;
	}
}

在这里插入图片描述


🌟 各位看官好,我是工藤新一¹呀~

🌈 愿各位心中所想,终有所致!
在这里插入图片描述

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值