一、问题描述
职工管理系统可以用来管理公司内所有员工的信息
本文主要利用 C++ 来实现一个基于多态的职工管理系统,公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位以及职责。
- 普通员工职责:完成经理派发的任务
- 经理职责:完成老板派发的任务,并下发任务给员工
- 老板职责:管理公司所有事物
管理系统中需要实现的功能如下:
- 退出管理系统:退出当前管理系统。
- 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号。
- 显示职工信息:显示公司内部所有职工的信息。
- 删除离职职工:按照编号删除指定的职工。
- 修改职工信息:按照编号修改职工个人信息。
- 查找职工信息:按照职工的编号或者职工的姓名进行查找相关人员信息。
- 按照编号排序:按照职工编号,进行排序,排序规则由用户指定。
- 清空所有文档:清空文件中记录的所有职工信息(清空前要再次确认,防止误删 )。
二、实现过程
创建抽象职工类 Worker.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
// 创建抽象职工类
class Worker
{
public:
// 显示个人信息
virtual void showInfo() = 0;
int m_IDnumber;
string m_Name;
string m_Post;
string m_Duty;
};
使用继承分别创建老板、经理、职工类,继承抽象职工类
老板类头文件(Boss.h):
#pragma once
#include <string>
#include <iostream>
#include "Worker.h"
using namespace std;
// 创建老板类
class Boss : public Worker
{
public:
Boss(int IDnumber,string name);
void showInfo();
};
具体实现(Boss.cpp)如下:
#include "Boss.h"
Boss::Boss(int IDnumber, string name)
{
m_IDnumber = IDnumber;
m_Name = name;
m_Post = "老板";
m_Duty = "管理公司所有事物";
}
void Boss::showInfo()
{
cout << "职工编号:" << this->m_IDnumber << "\t";
cout << "姓名:" << this->m_Name << "\t";
cout << "岗位:" << this->m_Post << "\t";
cout << "岗位职责:" << this->m_Duty << endl;
}
经理类头文件(Manager.h):
#pragma once
#include <string>
#include <iostream>
#include "Worker.h"
using namespace std;
// 创建经理类
class Manager : public Worker
{
public:
Manager(int IDnumber, string name);
void showInfo();
};
具体实现(Manager.cpp)如下:
#include "Manager.h"
Manager::Manager(int IDnumber, string name)
{
m_IDnumber = IDnumber;
m_Name = name;
m_Post = "经理";
m_Duty = "完成老板派发的任务,并下发任务给员工";
}
void Manager::showInfo()
{
cout << "职工编号:" << this->m_IDnumber << "\t";
cout << "姓名:" << this->m_Name << "\t";
cout << "岗位:" << this->m_Post << "\t";
cout << "岗位职责:" << this->m_Duty << endl;
}
普通员工类头文件(Staff.h):
#pragma once
#include <string>
#include <iostream>
#include "Worker.h"
using namespace std;
// 创建普通员工类
class Staff : public Worker
{
public:
Staff(int IDnumber, string name);
void showInfo();
};
具体实现(Staff.cpp)如下:
#include "Staff.h"
Staff::Staff(int IDnumber, string name)
{
m_IDnumber = IDnumber;
m_Name = name;
m_Post = "普通员工";
m_Duty = "完成经理派发的任务";
}
void Staff::showInfo()
{
cout << "职工编号:" << this->m_IDnumber << "\t";
cout << "姓名:" << this->m_Name << "\t";
cout << "岗位:" << this->m_Post << "\t";
cout << "岗位职责:" << this->m_Duty << endl;
}
在这一片段中,老板类、经理类、普通员工类继承了抽象职工类,并重写了父类中的纯虚函数virtual void showInfo() = 0
,以达到了动态多态的满足条件,在后文中便可使用多态。
创建职工管理系统类
在做好上一节中的准备工作之后,我们可以开始创建一个职工管理系统类,头文件(workerManager.h)如下:
#pragma once // 防止头文件重复包含
#define FILENAME "WorkerManager.txt"
#include <iostream>
#include <fstream>
#include "Worker.h"
#include "Boss.h"
#include "Manager.h"
#include "Staff.h"
using namespace std;
class workerManager
{
public:
// 构造函数
workerManager();
// 展示菜单
void showMenu();
// 退出系统
void existSystem();
// 添加职工
void AddWorkers();
// 保存到文件中
void save();
//获取文件中保存的职工数量
int getWorkerNum();
// 初始化职工
void initWorker();
// 显示职工
void showInfo();
// 判断职工是否存在
int isExist();
// 删除职工
void deleteWorker();
// 修改职工
void modifyWorker();
// 查找职工
void searchWorker();
// 编号排序
void sortWorker();
// 清空文档
void delAllWorker();
// 析构函数
~workerManager();
Worker ** m_wmArray; // 职工数组指针
int m_size; //记录职工人数
bool m_FileIsEmpty;
};
其中需要关注的是,Worker ** m_wmArray; // 职工数组指针
是一个二级指针,他指向一个每个元素都为指针的数组的首地址,数组中的指针再指向存有某个员工类的地址。
成员函数基本是根据需求描述来编写的,增加了个别在其他函数中需要用到的,比如int getWorkerNum();
可以获取文件中保存的职工数量,int isExist();
可以判断职工是否存在等。下面给出该职工管理类成员函数的具体实现(workerManager.cpp):
#include "workerManager.h"
#include <string>
// 构造函数
workerManager::workerManager()
{
ifstream ifs;
ifs.open(FILENAME, ios::in | ios::binary);
// 当文件不存在时进行初始化
if (!ifs.is_open())
{
this->m_size = 0;
this->m_FileIsEmpty = true;
this->m_wmArray = NULL;
ifs.close();
return;
}
// 文件存在且数据为空时进行初始化
char ch;
ifs >> ch;
if (ifs.eof())
{
this->m_size = 0;
this->m_FileIsEmpty = true;
this->m_wmArray = NULL;
ifs.close();
return;
}
// 文件存在且保存有职工数据
int num = this->getWorkerNum();
this->m_size = num;
// 开辟新空间并存放已有的职工信息
this->m_wmArray = new Worker*[this->m_size];
this->initWorker();
this->m_FileIsEmpty = false;
return;
}
// 展示菜单
void workerManager::showMenu()
{
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;
}
// 退出系统
void workerManager::existSystem()
{
cout << "欢迎下次使用!" << endl;
system("pause");
exit(0);
}
// 添加职工
void workerManager::AddWorkers()
{
cout << "请输入增加员工数量:";
int num_add = 0;
cin >> num_add;
if (num_add > 0)
{
// 计算新空间大小
int newSize = this->m_size + num_add;
// 开辟新空间
Worker** newspace = new Worker* [newSize];
// 将原空间下内容存放到新空间下
if(this->m_size != 0)
for (int i = 0; i < this->m_size; i++)
{
newspace[i] = this->m_wmArray[i];
}
// 输入新数据
for (int i = 0; i < num_add; i++)
{
int IDnumber;
string name;
int post_choice;
cout << "请输入第 " << i + 1 << " 个新员工的职工编号:";
cin >> IDnumber;
cout << "请输入该员工的姓名:";
cin >> name;
cout << "请输入该员工的岗位(1、老板;2、经理;3、普通员工。):";
cin >> post_choice;
Worker * wk = NULL;
switch (post_choice)
{
case 1:
wk = new Boss(IDnumber, name);
break;
case 2:
wk = new Manager(IDnumber, name);
break;
case 3:
wk = new Staff(IDnumber, name);
break;
default:
break;
}
// 将创建的职工指针保存到指针数组中
newspace[this->m_size + i] = wk;
}
// 释放原有空间
delete[] this->m_wmArray;
// 更新新空间指向
this->m_wmArray = newspace;
// 更新新的个数
this->m_size = newSize;
// 保存到文件中
this->save();
// 更新文件不为空标志
this->m_FileIsEmpty = false;
// 提示信息
cout << "成功添加 " << num_add << " 名新职工!" << endl;
}
else
{
cout << "输入有误!" << endl;
}
system("pause");
system("cls");
}
// 保存到文件中
void workerManager::save()
{
ofstream ofs;
ofs.open(FILENAME, ios::out | ios::binary);
for (int i = 0; i < this->m_size; i++)
{
ofs << this->m_wmArray[i]->m_IDnumber << "\t"
<< this->m_wmArray[i]->m_Name << "\t"
<< this->m_wmArray[i]->m_Post << "\t"
<< this->m_wmArray[i]->m_Duty << endl;
}
ofs.close();
}
// 获取文件中保存的职工数量
int workerManager::getWorkerNum()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id = 0;
string name;
string post;
string duty;
int num = 0;
while (ifs >> id && ifs >> name && ifs >> post && ifs >> duty)
{
num++;
}
ifs.close();
return num;
}
// 初始化员工
void workerManager::initWorker()
{
ifstream ifs;
ifs.open(FILENAME, ios::in);
int id = 0;
string name;
string post;
string duty;
int index = 0;
while (ifs >> id && ifs >> name && ifs >> post && ifs >> duty)
{
Worker * worker = NULL;
if (post == "普通员工")
{
worker = new Staff(id, name);
}
else if (post == "经理")
{
worker = new Manager(id, name);
}
else
{
worker = new Boss(id, name);
}
this->m_wmArray[index] = worker;
index++;
}
ifs.close();
}
// 显示职工
void workerManager::showInfo()
{
if (this->m_size == 0)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
for (int i = 0; i < this->m_size; i++)
{
// 利用多态调用程序接口
this->m_wmArray[i]->showInfo();
}
}
system("pause");
system("cls");
}
// 判断职工是否存在并返回在数组中的位置
int workerManager::isExist()
{
cout << "请输入查找职工信息方式(1、按职工编号查找;2、按姓名查找。):";
int sermethod_choice;
cin >> sermethod_choice;
int index = -1;
if (sermethod_choice == 1)
{
cout << "请输入职工编号:";
int ser_idnumber;
cin >> ser_idnumber;
for (int i = 0; i < this->m_size; i++)
{
if (this->m_wmArray[i]->m_IDnumber == ser_idnumber)
{
index = i;
break;
}
}
return index;
}
else
{
cout << "请输入职工姓名:";
string ser_name;
cin >> ser_name;
for (int i = 0; i < this->m_size; i++)
{
if (this->m_wmArray[i]->m_Name == ser_name)
{
index = i;
break;
}
}
return index;
}
}
// 删除职工
void workerManager::deleteWorker()
{
int del_index;
del_index = this->isExist();
if (del_index >= 0)
{
for (int i = del_index; i < this->m_size - 1; i++)
{
this->m_wmArray[i] = this->m_wmArray[i + 1];
}
this->m_size = this->m_size - 1;
this->save();
cout << "已成功删除该离职职工信息!" << endl;
}
else
{
cout << "在职职工中没有此职工!" << endl;
}
system("pause");
system("cls");
}
// 修改职工
void workerManager::modifyWorker()
{
int modify_index;
modify_index = this->isExist();
if (modify_index >= 0)
{
cout << "该职工的原信息为:" << endl;
this->m_wmArray[modify_index]->showInfo();
delete this->m_wmArray[modify_index];
int IDnumber;
string name;
int post_choice;
cout << "请输入该职工修改后的信息:" << endl;
cout << "职工编号:";
cin >> IDnumber;
cout << "姓名:";
cin >> name;
cout << "岗位(1、老板;2、经理;3、普通员工。):";
cin >> post_choice;
Worker * wk = NULL;
switch (post_choice)
{
case 1:
wk = new Boss(IDnumber, name);
break;
case 2:
wk = new Manager(IDnumber, name);
break;
case 3:
wk = new Staff(IDnumber, name);
break;
default:
cout << "输入有误!" << endl;
break;
}
m_wmArray[modify_index] = wk;
this->save();
cout << "已成功修改该职工信息!" << endl;
system("pause");
system("cls");
}
else
{
cout << "在职职工中没有此职工!" << endl;
system("pause");
system("cls");
}
}
// 查找职工
void workerManager::searchWorker()
{
int ser_index;
ser_index = this->isExist();
if (ser_index >= 0)
{
cout << "该职工的信息为:" << endl;
this->m_wmArray[ser_index]->showInfo();
system("pause");
system("cls");
}
else
{
cout << "在职职工中没有此职工!" << endl;
system("pause");
system("cls");
}
}
// 编号排序
void workerManager::sortWorker()
{
int sortMethod_choice;
cout << "请输入排序方式(1、按职工编号升序排序;2、按职工编号降序排序。):";
cin >> sortMethod_choice;
if (sortMethod_choice == 1)
{
for (int i = 0; i < this->m_size; i++)
{
for (int j = 0; j < this->m_size - i - 1; j++)
{
if (this->m_wmArray[j]->m_IDnumber > this->m_wmArray[j + 1]->m_IDnumber)
{
Worker *temp = this->m_wmArray[j];
this->m_wmArray[j] = this->m_wmArray[j + 1];
this->m_wmArray[j + 1] = temp;
}
}
}
this->save();
cout << "已成功将职工按照编号升序排列。" << endl;
system("pause");
system("cls");
}
else if (sortMethod_choice == 2)
{
for (int i = 0; i < this->m_size; i++)
{
for (int j = 0; j < this->m_size - i - 1; j++)
{
if (this->m_wmArray[j]->m_IDnumber < this->m_wmArray[j + 1]->m_IDnumber)
{
Worker *temp = this->m_wmArray[j];
this->m_wmArray[j] = this->m_wmArray[j + 1];
this->m_wmArray[j + 1] = temp;
}
}
}
this->save();
cout << "已成功将职工按照编号升序排列。" << endl;
system("pause");
system("cls");
}
else
{
cout << "输入有误!" << endl;
system("pause");
system("cls");
}
}
// 清空文档
void workerManager::delAllWorker()
{
cout << "请问您确认要清空文档吗?(1、确认;2、取消。)";
int del_choice;
cin >> del_choice;
switch (del_choice)
{
case 1:
{
// 清空文件
ofstream ofs(FILENAME, ios::trunc); // 删除文件后再重新创建
ofs.close();
// 是否堆区数据
if (this->m_wmArray != NULL)
{
for (int i = 0; i < this->m_size; i++)
{
if (this->m_wmArray[i] != NULL)
{
delete this->m_wmArray[i];
this->m_wmArray[i] = NULL;
}
}
delete[] this->m_wmArray;
this->m_wmArray = NULL;
this->m_size = 0;
this->m_FileIsEmpty = true;
}
cout << "已成功清空文档!" << endl;
break;
}
case 2:
cout << "已取消!" << endl;
break;
default:
cout << "输入有误!" << endl;
break;
}
system("pause");
system("cls");
}
//析构函数
workerManager::~workerManager()
{
if (this->m_wmArray != NULL)
{
for (int i = 0; i < this->m_size; i++)
{
if (this->m_wmArray[i] != NULL)
{
delete this->m_wmArray[i];
}
}
}
delete[] this->m_wmArray;
}
在主函数中使用该职工管理系统类
行文至此,我们的职工管理系统类的整个功能已搭建完毕,接下来就要在main文件中调用这个类,以真正运行职工管理系统,cpp如下:
#include <iostream>
#include <string>
#include <fstream>
#include "workerManager.h"
using namespace std;
int main()
{
workerManager WM;
int select;
int index;
while (true)
{
WM.showMenu();
cout << "请输入您的选择:";
cin >> select;
switch (select)
{
case 0: // 退出系统
WM.existSystem();
break;
case 1: // 添加职工
WM.AddWorkers();
break;
case 2: // 显示职工
WM.showInfo();
break;
case 3: // 删除职工
WM.deleteWorker();
break;
case 4: // 修改职工
WM.modifyWorker();
break;
case 5: // 查找职工
WM.searchWorker();
break;
case 6: // 编号排序
WM.sortWorker();
break;
case 7: // 清空文档
WM.delAllWorker();
break;
default:
system("cls");
break;
}
}
system("pause");
return 0;
}
三、测试
运行该项目后,出现如下对话框:
输入相应的数字并按下回车便可使用相应的功能,比如我们添加2个员工信息进去,输入数字1按下回车,然后按照提示输入相关信息:
添加完职工信息之后,可以选择显示职工信息:
删除、修改等功能便不再一一测试了,另外值得一提的是,这个职工管理系统将职工的信息都保存至一个txt文件中,每次打开此职工管理系统时,会自动将txt文件中的信息写进内存中,从而不会出现关闭系统再打开,信息就消失了的情况。
四、总结
这是OOP编程经典案例,刚入手写的还不是很熟练,觉得在写这个职工管理类之前,一定要先梳理好逻辑关系,确定要继承关系,以及数据管理方法等,总而言之,受益匪浅~