基于 C++多态 的职工管理系统

本文描述了一个员工管理系统的实现,包括添加(普通员工、经理、老板)、删除、显示、修改、查找、排序和清空等功能。系统基于C++,采用面向对象编程,利用文件存储员工信息。通过菜单选择实现各种操作,如按编号或姓名查找员工,按编号升序或降序排序等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1 管理系统概述

2 创建管理 类

3 各个接口函数

3.1 菜单展示功能

3.2 选择功能

3.3 创建员工功能

3.3.1 普通员工employee

3.3.2 经理manager

3.3.3 老板boss

3.3.4 测试

3.4 添加功能

3.4.1 添加员工

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

3.4.2.1写文件

3.4.2.2读文件

3.5 显示员工

3.6 删除员工

3.7 修改员工

3.8 查找员工

3.9 排序员工

3.10 清空文件


1 管理系统概述

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

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

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

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

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

具体实现的功能:

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

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

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

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

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

查找员工并显示其信息

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

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

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

2 创建管理 类

管理 类的作用:

  • 供用户选择的菜单界面

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

  • 与数据文件的读写交互


首先需要头文件与源文件

img

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

 #pragma once
 #include<iostream>
 using namespace std;
 ​
 class WorkerManager
 {
 public:
   // 构造函数
   WorkerManager();
   // 析构函数
   ~WorkerManager();
 };

并在源文件中空实现

 #include<iostream>
 using namespace std;
 #include"workerManager.h"
 ​
   // 构造函数
 WorkerManager::WorkerManager()
 {
 ​
 }
 // 析构函数
 WorkerManager::~WorkerManager()
 {
 ​
 }

3 各个接口函数

3.1 菜单展示功能

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

   void Show_Menu();

img

再在源文件中实现

 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;
 }

img


3.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.3 创建员工功能

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

 // 员工抽象类_基类
 ​
 class Worker
 {
 public:
   // 展示个人信息
   virtual void showInfo() = 0;
   // 获取个人岗位
   virtual string getDeptName() = 0;
 ​
   int m_id;   // 员工编号
   string m_name;// 员工姓名
   int m_Did;  // 所属部门编号
 };

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

3.3.1 普通员工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;
 }

img


3.3.2 经理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 "经理";
 }

3.3.3 老板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 "老板";
 }

3.3.4 测试

记得包含各个职位头文件

 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;
 }

img

3.4 添加功能

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

3.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函数后进行测试

img

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

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

3.4.2.1写文件

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

img

然后在源文件中实现:

 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函数中调用即可

img

3.4.2.2读文件

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

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


而文件实际有3种状态:

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

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

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


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

img

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

  • 文件不存在

 // 构造函数
 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()

img

在源文件中实现

 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;
   }

img

3.5 显示员工

直接调用showInfo()函数即可


分为3种情况:

  • 文件为空,没有员工

  • 文件存在,没有员工

  • 文件存在,有员工

前两种可以合并


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

img

然后在源文件中实现

 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"); // 清屏
 }

3.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"); // 清屏
 }

3.7 修改员工

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");
 }

3.8 查找员工

有2种方式:

  • 编号查找

  • 姓名查找

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


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

img

然后在源文件中实现:

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

同时,我们创建是否找到员工变量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");
 }

3.9 排序员工

2种方法:

  • 升序排列

  • 降序排列

我们使用选择排序

 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();
   }
 }

3.10 清空文件

先创建销毁函数

img

源文件中实现:

清空文件,再销毁数组

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

 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");
   }
 }

至此完成全部功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值