文章目录
- 一、创建管理类及菜单功能实现
- 二、创建职工抽象类
- 三、退出管理程序
- 四、增加职工信息
- 五、读写文件操作
- 六、显示职工信息
- 七、删除职工信息
- 八、修改职工信息
- 九、查找职工信息
- 十、对职工信息排序
- 十一、清空文件内容
- 十二、工程文件构成
本案例中利用C++实现一个基于多态的职工管理系统。公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名以及职工岗位。
 该管理系统需要具备如下功能:
 退出管理程序:退出当前管理系统;
 增加职工信息:可以实现批量添加职工信息的功能,并将信息写入到文件中,职工信息包括职工编号、姓名、部门编号;
 显示职工信息:显示公司内部所有职工的信息;
 删除职工信息:按照编号删除指定的职工信息;
 修改职工信息:根据编号修改职工的信息;
 查找职工信息:按照职工的编号或者职工的姓名查找相关的人员信息;
 对职工信息排序:根据职工编号进行排序,排序规则可以由用户指定;
 清空文件内容:清空文件中记录的所有职工信息,但在清空前需要再次确认,防止误删。
一、创建管理类及菜单功能实现
在写代码之前,先在Visual Studio中创建一个项目,然后新建一个C++文件。
 管理类完成的功能主要有:与用户的沟通菜单界面;对职工增删改查的操作;与文件的读写交互。
 为了文件之间功能清晰,分别创建头文件和C++文件用来创建管理类,如下图所示。
 
 WorkerManager.h头文件中暂时包括下面的内容。
#pragma once   //防止头文件重复包含
#include <iostream>
using namespace std;
class WorkerManager
{
public:
	WorkerManager();   //构造函数
	void show_menu();  //显示菜单函数的声明
	~WorkerManager();  //析构函数
};
WorkerManager.cpp文件中包含显示菜单函数的实现。
#include "workerManager.h"
WorkerManager::WorkerManager()
{
}
void WorkerManager::show_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;
}
WorkerManager::~WorkerManager()
{
}
main.cpp文件中简单的实例化一个管理类对象,然后调用菜单显示函数。
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#include "workerManager.h"
int main()
{
	WorkerManager wm;  //实例化一个对象
	wm.show_menu();  //调用成员函数显示菜单
	system("pause");
	return 0;
}
有以上代码之后,运行程序之后就可以显示菜单了,如下图所示。
 
 后面各个功能的实现只需要往里面添加函数就可以了。
二、创建职工抽象类
职工分为普通员工、经理、老板,写一个通用的父类,里面包含员工编号、员工姓名、员工所在部门编号,然后分别创建普通员工、经理和老板类继承父类,重写里面相应的函数。
 创建一个worker.h头文件,在里面创建职工抽象类,然后分别写子类继承抽象类重写其成员函数。
#pragma once   //防止头文件重复包含
#include <iostream>
#include <string>
using namespace std;
class Worker
{
public:
	//成员方法
	virtual void show_info() = 0;  //显示员工信息的纯虚函数
	virtual string get_dep() = 0;  //获取员工部门的纯虚函数
	//成员属性
	int worker_id;  //员工编号
	string name;  //员工姓名
	int dep_id;  //员工部门编号
};
class Employee : public Worker  //普通职工类
{
public:
	Employee(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "普通员工";
	}
};
class Manager : public Worker  //经理类
{
public:
	Manager(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "经理";
	}
};
class Boss : public Worker  //老板类
{
public:
	Boss(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "老板";
	}
};
在main.cpp中继承该头文件,使用如下代码进行测试。
Worker *w = new Employee(1,"张三",1);
	w->show_info();
	delete w;
	w = new Manager(2,"李四",2);
	w->show_info();
	delete w;
	w = new Boss(3,"王五",3);
	w->show_info();
	delete w;
测试结果如下图所示。
 
三、退出管理程序
退出管理系统就是在用户输入0之后退出系统,同样的先在管理类中声明函数,然后在相应的C++文件中实现函数,然后在main函数中通过实例化的对象调用函数退出管理程序。
 退出管理程序的函数实现如下。
void WorkerManager::exit_system() //退出系统函数的实现
{
	cout<<"欢迎下次继续使用!"<<endl;
	system("pause");  //按任意键继续
	exit(0);  //退出程序
}
主函数中根据用户输入的数字决定接下来要进行的操作。
int main()
{
	WorkerManager wm;  //实例化一个对象
	int menu_choice = 0;  //用户菜单选择
	while(1)
	{
		wm.show_menu();  //调用成员函数显示菜单
		cout<<"请输入您要操作的菜单编号:";
		cin>>menu_choice;
		switch(menu_choice)
		{
			case 0:  //退出管理程序
				wm.exit_system();
				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;
}
程序运行结果如下图所示。
 
四、增加职工信息
可以批量增加职工信息,职工信息需要保存到文件中。
 用户在批量创建时,可能会创建不同种类的职工,如果要将不同种类的员工信息存入到一个数组中,可以将所有职工的指针维护到一个数组里。如果想在程序中维护不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护。
 在WorkerManager.cpp文件中添加下面的代码增加职工信息,在添加新职工前需要先判断要添加的职工编号是否已经存在。
void WorkerManager::add_employee()  //添加职工信息函数的实现
{
	cout<<"请输入要添加职工的数量:";
	int add_num=0;
	cin>>add_num;
	if(add_num > 0)
	{
		int newsize = this->Num + add_num; //新空间的数组大小
		Worker **newspace = new Worker*[newsize];  //开辟新空间
		//如果原来的数组不为空就进行拷贝
		if(this->w_arr != NULL)
		{
			for(int i=0;i<this->Num;i++)
			{
				newspace[i] = this->w_arr[i];  //将原数组中的数据拷贝到扩展后的新数组中
			}
		}
		//批量添加职工信息
		for(int i=0;i<add_num;i++)
		{
			int w_id;
			string name;
			int d_id;
			cout<<"请输入第"<<i+1<<"个职工的职工编号:";
			cin>>w_id;
			while(1)   //根据职工编号判断职工信息是否已经存在
			{
				int j;
				for(j=0;j<this->Num+i;j++)
				{
					if(w_id == newspace[j]->worker_id)
					{
						break;
					}
				}
				if(j==this->Num+i)   //没有重复的职工编号
				{
					break;
				}
				else
				{
					cout<<"编号为"<<w_id<<"的职工信息已存在!"<<endl;
					cout<<"请重新输入第"<<i+1<<"个职工的职工编号:";
					cin>>w_id;
				}
			}
			cout<<"请输入第"<<i+1<<"个职工的职工姓名:";
			cin>>name;
			cout<<"1.普通职工"<<endl;
			cout<<"2.经理"<<endl;
			cout<<"3.老板"<<endl;
			cout<<"请选择该职工的岗位编号(1-3):";
			cin>>d_id;
			while(1)   //确保输入正确
			{
				if(d_id == 1||d_id == 2||d_id == 3)
					break;
				else
				{
					cout<<"职工岗位编号输入有误,请重新输入(1-3):";
					cin>>d_id;
				}
			}
			
			//保存输入员工的信息
			Worker *w = NULL;
			switch(d_id)
			{
				case 1:
					w = new Employee(w_id,name,d_id);
					break;
				case 2:
					w = new Manager(w_id,name,d_id);
					break;
				case 3:
					w = new Boss(w_id,name,d_id);
					break;
				default:
					break;
			}
			//将新添加的职工指针保存到数组指针中
			newspace[this->Num+i] = w;
		}
		delete []this->w_arr;   //释放原有数组
		this->w_arr = newspace;   //更新新空间的指向
		this->Num = newsize;   //更新人数
		this->save_to_file();  //保存数据到文件中
		this->fileIsEmpty = false;   //文件不为空
		cout<<"成功添加"<<add_num<<"名职工的信息!"<<endl;
	}
	else
	{
		cout<<"输入有误!"<<endl;
	}
	//按任意键返回上级并清屏
	system("pause");
	system("cls");
}
程序运行结果如下图所示。
 
五、读写文件操作
每次重新运行程序的时候,数组中存放的内容都是空的,上一次运行后的数据在程序结束时会被删除,这不太符合实际,应当将每次运行程序后添加的数据写入到文件中,这样在程序再次运行时,数据也是存在的。
 将新添加的职工数据写入到文件中的函数实现如下。
void WorkerManager::save_to_file()  //将数据保存到文件的函数实现
{
	ofstream ofs;
	ofs.open(FILENAME,ios::out);  //往文件中写数据
	//将所有员工的数据写入到文件中
	//ofs <<"职工编号\t"<<"职工姓名\t"<<"职工部门"<<endl;
	for(int i=0;i<this->Num;i++)
	{
		ofs << w_arr[i]->worker_id<<"\t"
			<< w_arr[i]->name<<"\t"
			<< w_arr[i]->dep_id<<endl;
	}
	ofs.close();
}
可以看到,用户输入的各项信息成功的写入到了文件中。
 
 还有读文件的操作,文件的状态在本案例中应当有三种。第一种是文件不存在,在第一次添加员工后,文件才会创建;第二种是文件存在,但是里面的内容为空,就是添加员工信息之后又删除了;第三种是文件存在且里面的内容不为空,这种情况就比较复杂,需要将文件中记录的员工数量进行统计,然后再对相关属性进行初始化。
 WorkerManager.cpp文件中的相关函数如下。
int WorkerManager::getEmpNum()   //统计文件中的职工个数的函数实现
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);  //读文件
	int w_id;
	string name;
	int d_id;
	int num=0;
	while(ifs>>w_id && ifs>>name && ifs>>d_id)
	{
		num++;
	}
	return num;
}
void WorkerManager::initEmp()  //初始化员工的函数实现
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);
	int w_id;
	string name;
	int d_id;
	int index=0;
	while(ifs>>w_id && ifs>>name && ifs>>d_id)
	{
		Worker *w = NULL;
		if(d_id==1)
		{
			w = new Employee(w_id,name,d_id);  //普通员工
		}
		else if(d_id==2)
		{
			w = new Manager(w_id,name,d_id);  //经理
		}
		else
		{
			w = new Boss(w_id,name,d_id);  //老板
		}
		this->w_arr[index] = w;  //存放到数组中
		index++;
	}
	ifs.close();
}
构造函数中对应三种情况的初始化代码如下。
WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);  //读文件
	//1.文件不存在
	if(!ifs.is_open())   
	{
		//初始化属性
		this->Num = 0;
		this->w_arr = NULL;
		this->fileIsEmpty = true;
		ifs.close();
		return;   //返回,不进行后续操作
	}
	
	//2.文件存在且内容为空
	char ch;
	ifs >> ch;  //读一个字符
	if(ifs.eof())   
	{
		//初始化属性
		this->Num = 0;
		this->w_arr = NULL;
		this->fileIsEmpty = true;
		ifs.close();
		return;   //返回,不进行后续操作
	}
	//3.文件存在且内容不为空
	this->fileIsEmpty = false;
	int num = this->getEmpNum();  //获取文件中已有的职工数量
	//初始化属性
	this->Num = num; 
	this->w_arr = new Worker*[this->Num];  //在堆区开辟数组
	this->initEmp();  //将文件中的数据保存到数组
}
六、显示职工信息
显示职工信息比较简单,首先判断文件是否存在,如果不存在就打印提示信息,如果存在就将所有的职工信息进行输出。
void WorkerManager::display_employee()  //显示职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,没有可显示的内容!"<<endl;
	}
	else
	{
		for(int i=0;i<this->Num;i++)
		{
			this->w_arr[i]->show_info();  //显示职工信息
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
程序运行的结果如下图所示。
 
 如果将文件删除,再次运行程序,结果如下图所示。
 
七、删除职工信息
删除职工信息需要注意将职工的数量和数组指针做同步的更新,并将信息在文件中也做同步更新。
 在删除职工信息之前需要先判断该职工信息是否存在,删除职工信息的函数实现如下。
int WorkerManager::isExist(int id)   //判断职工是否存在的函数实现
{
	for(int i=0;i<this->Num;i++)
	{
		if(this->w_arr[i]->worker_id == id)
			return i;
	}
	return -1;
}
void WorkerManager::delete_employee()  //删除职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行删除操作!"<<endl;
	}
	else
	{
		int w_id,ret;
		cout<<"请输入要删除的职工编号:";
		cin>>w_id;
		ret = this->isExist(w_id);
		if(ret != -1) 
		{
			for(int i=ret;i<this->Num-1;i++)
			{
				this->w_arr[i] = this->w_arr[i+1];
			}
			this->Num--;  //更新数组中存放的元素个数
			this->save_to_file();  //数据同步更新到文件中
			cout<<"已删除职工编号为"<<w_id<<"的职工信息!"<<endl;
		}
		else
		{
			cout<<"职工编号为"<<w_id<<"的职工不存在,删除失败!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
先显示一下现有的职工信息,如下图所示。
 
 然后删除掉其中的一个职工的信息,如下图所示,提示删除成功。
 
 再次显示职工信息,如下图所示,删除确实成功了。
 
 再打开对应的文件查看内容,如下图所示,信息是同步的,文件中的数据也被删除掉了。
 
 如果输入一个不存在的职工编号,会出现如下图所示的提示信息。
 
八、修改职工信息
修改职工信息时,再查找到对应的职工编号后,删除原有记录,然后根据用户输入在该位置添加新的职工信息。
 修改职工信息的函数实现代码如下。
void WorkerManager::modify_employee()  //修改职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行修改操作!"<<endl;
	}
	else
	{
		int w_id,ret;
		cout<<"请输入要修改的职工编号:";
		cin>>w_id;
		ret = this->isExist(w_id);
		if(ret != -1)
		{
			delete this->w_arr[ret];
			int new_id;
			string new_name;
			int new_d_id;
			cout<<"职工编号为"<<w_id<<"的职工信息存在,请输入新的职工编号:";
			cin>>new_id;
			cout<<"请输入新的职工姓名:";
			cin>>new_name;
			cout<<"1.普通职工"<<endl;
			cout<<"2.经理"<<endl;
			cout<<"3.老板"<<endl;
			cout<<"请选择该职工的岗位编号(1-3):";
			cin>>new_d_id;
			while(1)   //确保输入正确
			{
				if(new_d_id == 1||new_d_id == 2||new_d_id == 3)
					break;
				else
				{
					cout<<"职工岗位编号输入有误,请重新输入(1-3):";
					cin>>new_d_id;
				}
			}
			
			//保存输入员工的信息
			Worker *w = NULL;
			switch(new_d_id)
			{
				case 1:
					w = new Employee(new_id,new_name,new_d_id);
					break;
				case 2:
					w = new Manager(new_id,new_name,new_d_id);
					break;
				case 3:
					w = new Boss(new_id,new_name,new_d_id);
					break;
				default:
					break;
			}
			//将修改的职工指针保存到数组指针中
			this->w_arr[ret] = w;
			this->save_to_file();  //数据同步更新到文件中
			cout<<"职工编号为"<<w_id<<"的职工信息修改成功!"<<endl;
		}
		else
		{
			cout<<"职工编号为"<<w_id<<"的职工不存在!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
程序运行后同样先显示职工信息,如下图所示。
 
 然后修改职工信息,修改过程如下图所示。
 
 修改完成后再显示职工信息如下图所示。
 
 修改完成后,再输入旧的职工编号进行修改,提示该职工不存在。
 
 修改完成后,打开文件如下图所示,信息都同步更新了!
 
九、查找职工信息
查找职工信息可以按照职工编号查询,也可以按照职工姓名进行查询。
 查找职工信息的函数实现代码如下。
void WorkerManager::find_employee()  //查找职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行查找操作!"<<endl;
	}
	else
	{
		cout<<"1.按职工编号查"<<endl;
		cout<<"2.按职工姓名查"<<endl;
		cout<<"请选择要查找的方式(1-2):";
		int select;
		cin>>select;
		while(1)   //确保输入正确
		{
			if(select == 1||select == 2)
				break;
			else
			{
				cout<<"输入有误,请重新选择要查找的方式(1-2):";
				cin>>select;
			}
		}
		if(select==1)  //按职工编号查
		{
			cout<<"请输入要查找的职工编号:";
			int id;
			cin>>id;
			if(isExist(id)!=-1)
			{
				cout<<"查找成功,该职工的信息如下:"<<endl;
				this->w_arr[isExist(id)]->show_info();
			}
			else
			{
				cout<<"职工编号为"<<id<<"的职工信息不存在!"<<endl;
			}
		}
		else  //按职工姓名查
		{
			cout<<"请输入要查找的职工姓名:";
			bool flag=false;
			string name;
			cin>>name;
			for(int i=0;i<this->Num;i++)
			{
				if(name==this->w_arr[i]->name)
				{
					if(!flag)
					{
						cout<<"查找成功,职工的信息如下:"<<endl;
					}
					this->w_arr[i]->show_info();
					flag=true;
				}
			}
			if(!flag)
			{
				cout<<"职工姓名为"<<name<<"的职工信息不存在!"<<endl;
			}
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
程序运行后还是先显示一下职工信息,如下图所示。
 
 按照职工编号查询的过程如下图所示。
 
 按照职工姓名查询的过程如下图所示,按照职工姓名查询时可能会遇到重名的职工,要将所有同名的职工信息都进行打印。
 
 按照职工编号查询不存在的情况如下图所示。
 
 按照职工姓名查询不存在的情况如下图所示。
 
十、对职工信息排序
对职工信息排序时按照职工编号进行排序,具体是升序还是降序由用户选择。
 对职工信息排序的函数代码实现如下。
void WorkerManager::sort_employee()  //对职工信息排序的函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行排序操作!"<<endl;
		//按任意键后清屏
		system("pause");
		system("cls");
	}
	else
	{
		cout<<"1.按照职工编号升序排列"<<endl;
		cout<<"2.按照职工编号降序排列"<<endl;
		cout<<"请选择要排序的方式(1-2):";
		int select;
		cin>>select;
		while(1)   //确保输入正确
		{
			if(select == 1||select == 2)
				break;
			else
			{
				cout<<"输入有误,请重新选择要排序的方式(1-2):";
				cin>>select;
			}
		}
		
		for(int i=0;i<this->Num;i++)
		{
			int m=i;
			for(int j=i+1;j<this->Num;j++)
			{
				if(select == 1)  //按照职工编号升序排列
				{
					if(this->w_arr[j]->worker_id < this->w_arr[m]->worker_id)
					{
						m = j;
					}
				}
				else  //按照职工编号降序排列
				{
					if(this->w_arr[j]->worker_id > this->w_arr[m]->worker_id)
					{
						m = j;
					}
				}
			}
			if(m != i)  //m的值有变化就交换
			{
				Worker *temp = w_arr[i];
				w_arr[i] = w_arr[m];
				w_arr[m] = temp;
			}
		}
		this->save_to_file();   //将信息同步到文件中
		cout<<"排序成功!排序后的结果如下:"<<endl;
		this->display_employee();  //该函数中有按任意键后清屏操作
	}
}
程序运行后先显示一下职工信息,如下图所示,是无序的。
 
 选择按职工编号升序排列的执行过程如下图所示。
 
 选择按职工编号降序排列的执行过程如下图所示。
 
 文件中的信息如下图所示,也是同步变化的。
 
十一、清空文件内容
清空文件内容需要在文件打开方式中将其设置为 ios::trunc,如果文件存在就先删除,再创建。然后需要操作的就是将数组中的数据清空,同时将职工总数量设置为0。
 清空文件内容函数的代码如下。
void WorkerManager::clear_file()  //清空文件的函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或已经为空!"<<endl;
	}
	else
	{
		cout<<"1.确定"<<endl;
		cout<<"2.取消"<<endl;
		cout<<"确定清空文件数据?";
		int select;
		cin>>select;
		if(select==1)
		{
			ofstream ofs;
			ofs.open(FILENAME,ios::trunc);  //文件存在就删除文件,并重新创建
			ofs.close();
			//释放堆区内存
			if(this->w_arr != NULL)
			{
				for(int i=0;i<this->Num;i++)  //将每个元素都置空
				{
					delete this->w_arr[i];
					this->w_arr[i] = NULL;
				}
				delete []this->w_arr;   //删除并置空堆区数组指针
				this->w_arr = NULL;
			}
			//初始化属性
			this->Num = 0;
			this->fileIsEmpty = true;
			cout<<"文件清空成功!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
程序运行后先显示职工信息,如下图所示。
 
 清空后打开文件如下图所示,文件内容也被清空了。
 
 文件被清空后,只能选择菜单0退出程序或菜单1增加职工信息,其它操作均不能进行。
 文件被清空后执行显示操作如下图所示。
 
 文件被清空后执行删除操作如下图所示。
 
 文件被清空后执行修改操作如下图所示。
 
 文件被清空后执行查找操作如下图所示。
 
 文件被清空后执行排序操作如下图所示。
 
 文件被清空后执行清空文件的操作如下图所示。
 
十二、工程文件构成
本案例的工程主要包含以下四个文件。
 
 worker.h文件的内容如下。
#pragma once   //防止头文件重复包含
#include <iostream>
#include <string>
using namespace std;
class Worker
{
public:
	//成员方法
	virtual void show_info() = 0;  //显示员工信息的纯虚函数
	virtual string get_dep() = 0;  //获取员工部门的纯虚函数
	//成员属性
	int worker_id;  //员工编号
	string name;  //员工姓名
	int dep_id;  //员工部门编号
};
class Employee : public Worker  //普通职工类
{
public:
	Employee(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "普通员工";
	}
};
class Manager : public Worker  //经理类
{
public:
	Manager(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "经理";
	}
};
class Boss : public Worker  //老板类
{
public:
	Boss(int worker_id,string name,int dep_id)
	{
		this->worker_id = worker_id;
		this->name = name;
		this->dep_id = dep_id;
	}
	void show_info()  //显示员工信息的函数实现
	{
		cout<<"职工编号:"<<worker_id<<"\t职工姓名:"<<name<<"\t职工岗位:"<<get_dep()<<endl;
	}
	string get_dep()  //获取员工部门的函数实现
	{
		return "老板";
	}
};
workerManager.h文件的内容如下。
#pragma once   //防止头文件重复包含
#include <iostream>
#include <fstream>  //文件操作的头文件
using namespace std;
#include "worker.h"
#define FILENAME "Employee.txt"  //宏定义文件名称
class WorkerManager
{
public:
	WorkerManager();   //构造函数
	void show_menu();  //显示菜单函数的声明
	void exit_system();  //退出系统函数的声明
	int Num;   //总人数
	Worker **w_arr;  //存放职工的数组指针
	void add_employee();  //添加职工信息函数声明
	void save_to_file();  //将数据保存到文件的函数声明
	bool fileIsEmpty;   //文件是否为空的标志
	int getEmpNum();   //统计文件中的职工个数的函数声明
	void initEmp();   //初始化员工的函数声明
	void display_employee();  //显示职工信息函数声明
	int isExist(int id);   //判断职工是否存在的函数声明
	void delete_employee();  //删除职工信息函数声明
	void modify_employee();  //修改职工信息函数声明
	void find_employee();  //查找职工信息函数声明
	void sort_employee();  //对职工信息排序的函数声明
	void clear_file();  //清空文件的函数声明
	~WorkerManager();  //析构函数
};
main.cpp文件的内容如下。
#include <iostream>
#include <string>
using namespace std;
#include "workerManager.h"
#include "worker.h"
int main()
{
	WorkerManager wm;  //实例化一个对象
	int menu_choice = 0;  //用户菜单选择
	while(1)
	{
		wm.show_menu();  //调用成员函数显示菜单
		cout<<"请输入您要操作的菜单编号:";
		cin>>menu_choice;
		switch(menu_choice)
		{
			case 0:  //退出管理程序
				wm.exit_system();
				break;
			case 1:  //增加职工信息
				wm.add_employee();
				break;
			case 2:  //显示职工信息
				wm.display_employee();
				break;
			case 3:  //删除职工信息
				wm.delete_employee();
				break;
			case 4:  //修改职工信息
				wm.modify_employee();
				break;
			case 5:  //查找职工信息
				wm.find_employee();
				break;
			case 6:  //按照选择排序
				wm.sort_employee();
				break;
			case 7:  //清空所有信息
				wm.clear_file();
				break;
			default:
				system("cls");  //清屏操作
				break;
		}
	}
	system("pause");
	return 0;
}
WorkerManager.cpp文件中的内容如下。
#include "workerManager.h"
WorkerManager::WorkerManager()
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);  //读文件
	//1.文件不存在
	if(!ifs.is_open())   
	{
		//初始化属性
		this->Num = 0;
		this->w_arr = NULL;
		this->fileIsEmpty = true;
		ifs.close();
		return;   //返回,不进行后续操作
	}
	
	//2.文件存在且内容为空
	char ch;
	ifs >> ch;  //读一个字符
	if(ifs.eof())   
	{
		//初始化属性
		this->Num = 0;
		this->w_arr = NULL;
		this->fileIsEmpty = true;
		ifs.close();
		return;   //返回,不进行后续操作
	}
	//3.文件存在且内容不为空
	this->fileIsEmpty = false;
	int num = this->getEmpNum();  //获取文件中已有的职工数量
	//初始化属性
	this->Num = num; 
	this->w_arr = new Worker*[this->Num];  //在堆区开辟数组
	this->initEmp();  //将文件中的数据保存到数组
}
void WorkerManager::show_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;
}
void WorkerManager::exit_system() //退出系统函数的实现
{
	cout<<"欢迎下次继续使用!"<<endl;
	system("pause");  //按任意键继续
	exit(0);  //退出程序
}
void WorkerManager::add_employee()  //添加职工信息函数的实现
{
	cout<<"请输入要添加职工的数量:";
	int add_num=0;
	cin>>add_num;
	if(add_num > 0)
	{
		int newsize = this->Num + add_num; //新空间的数组大小
		Worker **newspace = new Worker*[newsize];  //开辟新空间
		//如果原来的数组不为空就进行拷贝
		if(this->w_arr != NULL)
		{
			for(int i=0;i<this->Num;i++)
			{
				newspace[i] = this->w_arr[i];  //将原数组中的数据拷贝到扩展后的新数组中
			}
		}
		//批量添加职工信息
		for(int i=0;i<add_num;i++)
		{
			int w_id;
			string name;
			int d_id;
			cout<<"请输入第"<<i+1<<"个职工的职工编号:";
			cin>>w_id;
			while(1)      //根据职工编号判断职工信息是否已经存在
			{
				int j;
				for(j=0;j<this->Num+i;j++)
				{
					if(w_id == newspace[j]->worker_id)
					{
						break;
					}
				}
				if(j==this->Num+i)   //没有重复的职工编号
				{
					break;
				}
				else
				{
					cout<<"编号为"<<w_id<<"的职工信息已存在!"<<endl;
					cout<<"请重新输入第"<<i+1<<"个职工的职工编号:";
					cin>>w_id;
				}
			}
			cout<<"请输入第"<<i+1<<"个职工的职工姓名:";
			cin>>name;
			cout<<"1.普通职工"<<endl;
			cout<<"2.经理"<<endl;
			cout<<"3.老板"<<endl;
			cout<<"请选择该职工的岗位编号(1-3):";
			cin>>d_id;
			while(1)   //确保输入正确
			{
				if(d_id == 1||d_id == 2||d_id == 3)
					break;
				else
				{
					cout<<"职工岗位编号输入有误,请重新输入(1-3):";
					cin>>d_id;
				}
			}
			
			//保存输入员工的信息
			Worker *w = NULL;
			switch(d_id)
			{
				case 1:
					w = new Employee(w_id,name,d_id);
					break;
				case 2:
					w = new Manager(w_id,name,d_id);
					break;
				case 3:
					w = new Boss(w_id,name,d_id);
					break;
				default:
					break;
			}
			//将新添加的职工指针保存到数组指针中
			newspace[this->Num+i] = w;
		}
		delete []this->w_arr;   //释放原有数组
		this->w_arr = newspace;   //更新新空间的指向
		this->Num = newsize;   //更新人数
		this->save_to_file();  //保存数据到文件中
		this->fileIsEmpty = false;   //文件不为空
		cout<<"成功添加"<<add_num<<"名职工的信息!"<<endl;
	}
	else
	{
		cout<<"输入有误!"<<endl;
	}
	//按任意键返回上级并清屏
	system("pause");
	system("cls");
}
void WorkerManager::save_to_file()  //将数据保存到文件的函数实现
{
	ofstream ofs;
	ofs.open(FILENAME,ios::out);  //往文件中写数据
	//将所有员工的数据写入到文件中
	//ofs <<"职工编号\t"<<"职工姓名\t"<<"职工部门"<<endl;
	for(int i=0;i<this->Num;i++)
	{
		ofs << w_arr[i]->worker_id<<"\t"
			<< w_arr[i]->name<<"\t"
			<< w_arr[i]->dep_id<<endl;
	}
	ofs.close();
}
int WorkerManager::getEmpNum()   //统计文件中的职工个数的函数实现
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);  //读文件
	int w_id;
	string name;
	int d_id;
	int num=0;
	while(ifs>>w_id && ifs>>name && ifs>>d_id)
	{
		num++;
	}
	return num;
}
void WorkerManager::initEmp()  //初始化员工的函数实现
{
	ifstream ifs;
	ifs.open(FILENAME,ios::in);
	int w_id;
	string name;
	int d_id;
	int index=0;
	while(ifs>>w_id && ifs>>name && ifs>>d_id)
	{
		Worker *w = NULL;
		if(d_id==1)
		{
			w = new Employee(w_id,name,d_id);  //普通员工
		}
		else if(d_id==2)
		{
			w = new Manager(w_id,name,d_id);  //经理
		}
		else
		{
			w = new Boss(w_id,name,d_id);  //老板
		}
		this->w_arr[index] = w;  //存放到数组中
		index++;
	}
	ifs.close();
}
void WorkerManager::display_employee()  //显示职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,没有可显示的内容!"<<endl;
	}
	else
	{
		for(int i=0;i<this->Num;i++)
		{
			this->w_arr[i]->show_info();  //显示职工信息
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
int WorkerManager::isExist(int id)   //判断职工是否存在的函数实现
{
	for(int i=0;i<this->Num;i++)
	{
		if(this->w_arr[i]->worker_id == id)
			return i;
	}
	return -1;
}
void WorkerManager::delete_employee()  //删除职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行删除操作!"<<endl;
	}
	else
	{
		int w_id,ret;
		cout<<"请输入要删除的职工编号:";
		cin>>w_id;
		ret = this->isExist(w_id);
		if(ret != -1)
		{
			for(int i=ret;i<this->Num-1;i++)
			{
				this->w_arr[i] = this->w_arr[i+1];
			}
			this->Num--;  //更新数组中存放的元素个数
			this->save_to_file();  //数据同步更新到文件中
			cout<<"已删除职工编号为"<<w_id<<"的职工信息!"<<endl;
		}
		else
		{
			cout<<"职工编号为"<<w_id<<"的职工不存在,删除失败!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
void WorkerManager::modify_employee()  //修改职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行修改操作!"<<endl;
	}
	else
	{
		int w_id,ret;
		cout<<"请输入要修改的职工编号:";
		cin>>w_id;
		ret = this->isExist(w_id);
		if(ret != -1)
		{
			delete this->w_arr[ret];
			int new_id;
			string new_name;
			int new_d_id;
			cout<<"职工编号为"<<w_id<<"的职工信息存在,请输入新的职工编号:";
			cin>>new_id;
			cout<<"请输入新的职工姓名:";
			cin>>new_name;
			cout<<"1.普通职工"<<endl;
			cout<<"2.经理"<<endl;
			cout<<"3.老板"<<endl;
			cout<<"请选择该职工的岗位编号(1-3):";
			cin>>new_d_id;
			while(1)   //确保输入正确
			{
				if(new_d_id == 1||new_d_id == 2||new_d_id == 3)
					break;
				else
				{
					cout<<"职工岗位编号输入有误,请重新输入(1-3):";
					cin>>new_d_id;
				}
			}
			
			//保存输入员工的信息
			Worker *w = NULL;
			switch(new_d_id)
			{
				case 1:
					w = new Employee(new_id,new_name,new_d_id);
					break;
				case 2:
					w = new Manager(new_id,new_name,new_d_id);
					break;
				case 3:
					w = new Boss(new_id,new_name,new_d_id);
					break;
				default:
					break;
			}
			//将修改的职工指针保存到数组指针中
			this->w_arr[ret] = w;
			this->save_to_file();  //数据同步更新到文件中
			cout<<"职工编号为"<<w_id<<"的职工信息修改成功!"<<endl;
		}
		else
		{
			cout<<"职工编号为"<<w_id<<"的职工不存在!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
void WorkerManager::find_employee()  //查找职工信息函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行查找操作!"<<endl;
	}
	else
	{
		cout<<"1.按职工编号查"<<endl;
		cout<<"2.按职工姓名查"<<endl;
		cout<<"请选择要查找的方式(1-2):";
		int select;
		cin>>select;
		while(1)   //确保输入正确
		{
			if(select == 1||select == 2)
				break;
			else
			{
				cout<<"输入有误,请重新选择要查找的方式(1-2):";
				cin>>select;
			}
		}
		if(select==1)  //按职工编号查
		{
			cout<<"请输入要查找的职工编号:";
			int id;
			cin>>id;
			if(isExist(id)!=-1)
			{
				cout<<"查找成功,该职工的信息如下:"<<endl;
				this->w_arr[isExist(id)]->show_info();
			}
			else
			{
				cout<<"职工编号为"<<id<<"的职工信息不存在!"<<endl;
			}
		}
		else  //按职工姓名查
		{
			cout<<"请输入要查找的职工姓名:";
			bool flag=false;
			string name;
			cin>>name;
			for(int i=0;i<this->Num;i++)
			{
				if(name==this->w_arr[i]->name)
				{
					if(!flag)
					{
						cout<<"查找成功,职工的信息如下:"<<endl;
					}
					this->w_arr[i]->show_info();
					flag=true;
				}
			}
			if(!flag)
			{
				cout<<"职工姓名为"<<name<<"的职工信息不存在!"<<endl;
			}
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
void WorkerManager::sort_employee()  //对职工信息排序的函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或记录为空,无法进行排序操作!"<<endl;
		//按任意键后清屏
		system("pause");
		system("cls");
	}
	else
	{
		cout<<"1.按照职工编号升序排列"<<endl;
		cout<<"2.按照职工编号降序排列"<<endl;
		cout<<"请选择要排序的方式(1-2):";
		int select;
		cin>>select;
		while(1)   //确保输入正确
		{
			if(select == 1||select == 2)
				break;
			else
			{
				cout<<"输入有误,请重新选择要排序的方式(1-2):";
				cin>>select;
			}
		}
		
		for(int i=0;i<this->Num;i++)
		{
			int m=i;
			for(int j=i+1;j<this->Num;j++)
			{
				if(select == 1)  //按照职工编号升序排列
				{
					if(this->w_arr[j]->worker_id < this->w_arr[m]->worker_id)
					{
						m = j;
					}
				}
				else  //按照职工编号降序排列
				{
					if(this->w_arr[j]->worker_id > this->w_arr[m]->worker_id)
					{
						m = j;
					}
				}
			}
			if(m != i)  //m的值有变化就交换
			{
				Worker *temp = w_arr[i];
				w_arr[i] = w_arr[m];
				w_arr[m] = temp;
			}
		}
		this->save_to_file();   //将信息同步到文件中
		cout<<"排序成功!排序后的结果如下:"<<endl;
		this->display_employee();  //该函数中有按任意键后清屏操作
	}
}
void WorkerManager::clear_file()  //清空文件的函数实现
{
	if(this->fileIsEmpty)
	{
		cout<<"文件不存在或已经为空!"<<endl;
	}
	else
	{
		cout<<"1.确定"<<endl;
		cout<<"2.取消"<<endl;
		cout<<"确定清空文件数据?";
		int select;
		cin>>select;
		if(select==1)
		{
			ofstream ofs;
			ofs.open(FILENAME,ios::trunc);  //文件存在就删除文件,并重新创建
			ofs.close();
			//释放堆区内存
			if(this->w_arr != NULL)
			{
				for(int i=0;i<this->Num;i++)  //将每个元素都置空
				{
					delete this->w_arr[i];
					this->w_arr[i] = NULL;
				}
				delete []this->w_arr;   //删除并置空堆区数组指针
				this->w_arr = NULL;
			}
			//初始化属性
			this->Num = 0;
			this->fileIsEmpty = true;
			cout<<"文件清空成功!"<<endl;
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}
WorkerManager::~WorkerManager()
{
	//释放堆区内存
	if(this->w_arr != NULL)
	{
		for(int i=0;i<this->Num;i++)  //将每个元素都置空
		{
			delete this->w_arr[i];
			this->w_arr[i] = NULL;
		}
		delete []this->w_arr;   //删除并置空堆区数组指针
		this->w_arr = NULL;
	}
}
本文的项目工程文件:点此下载
本文参考视频:
 黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难












![【蓝桥杯冲冲冲】[NOIP2001 普及组] 装箱问题](https://img-blog.csdnimg.cn/direct/6e67173901fe4580b2975a4c0c11abb1.jpeg#pic_center)






