【带你敲】职工管理系统(中)

简介: 笔记

6、创建职工类


6.1 创建职工抽象类

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


将三种职工抽象到一个类(worker)中,利用多态管理不同职工种类


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


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


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


#pragma once
#include<iostream>
#include<string>
using namespace std;
//职工抽象基类
class Worker
{
public:
  //显示个人信息
  virtual void showInfo() = 0;
  //获取岗位名称
  virtual string getDeptName() = 0;
  int m_Id; //职工编号
  string m_Name; //职工姓名
  int m_DeptId; //职工所在部门名称编号
};

6.2 创建普通员工类

普通员工类继承职工抽象类,并重写父类中纯虚函数


在头文件和源文件的文件夹下分别创建employee.h 和 employee.cpp文件


employee.h中代码如下:

#pragma once 
#include<iostream>
using namespace std;
#include "worker.h"
//员工类
class Employee :public Worker
{
public:
  //构造函数
  Employee(int id, string name, int dId);
  //显示个人信息
  virtual void showInfo();
  //获取职工岗位名称
  virtual string getDeptName();
};
employee.cpp中代码如下:
#include "employee.h"
Employee::Employee(int id, string name, int dId)
{
  this->m_Id = id;
  this->m_Name = name;
  this->m_DeptId = dId;
}
void Employee::showInfo()
{
  cout << "职工编号: " << this->m_Id
  << " \t职工姓名: " << this->m_Name
  << " \t岗位:" << this->getDeptName()
  << " \t岗位职责:完成经理交给的任务" << endl;
}
string Employee::getDeptName()
{
  return string("员工");
}

6.3 创建经理类

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


在头文件和源文件的文件夹下分别创建manager.h 和 manager.cpp文件


manager.h中代码如下:


#pragma once
#include<iostream>
using namespace std;
#include "worker.h"
//经理类
class Manager :public Worker
{
public:
  Manager(int id, string name, int dId);
  //显示个人信息
  virtual void showInfo();
  //获取职工岗位名称
  virtual string getDeptName();
};
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岗位:" << this->getDeptName()
  << " \t岗位职责:完成老板交给的任务,并下发任务给员工" << endl;
}
string Manager::getDeptName()
{
  return string("经理");
}


6.4 创建老板类

老板类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似


在头文件和源文件的文件夹下分别创建boss.h 和 boss.cpp文件


boss.h中代码如下:


#pragma once
#include<iostream>
using namespace std;
#include "worker.h"
//老板类
class Boss :public Worker
{
public:
  Boss(int id, string name, int dId);
  //显示个人信息
  virtual void showInfo();
  //获取职工岗位名称
  virtual string getDeptName();
};
boss.cpp中代码如下:
#include "boss.h"
Boss::Boss(int id, string name, int dId)
{
  this->m_Id = id;
  this->m_Name = name;
  this->m_DeptId = dId;
}
void Boss::showInfo()
{
  cout << "职工编号: " << this->m_Id
  << " \t职工姓名: " << this->m_Name
  << " \t岗位:" << this->getDeptName()
  << " \t岗位职责:管理公司所有事务" << endl;
}
string Boss::getDeptName()
{
  return string("总裁");
}


6.5 测试多态

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


测试代码如下:


#include "worker.h"
#include "employee.h"
#include "manager.h"
#include "boss.h"
void test()
{
  Worker * worker = NULL;
  worker = new Employee(1, "张三", 1);
  worker->showInfo();
  delete worker;
  worker = new Manager(2, "李四", 2);
  worker->showInfo();
  delete worker;
  worker = new Boss(3, "王五", 3);
  worker->showInfo();
  delete worker;
}


运行效果如图:

4.png

测试成功后,测试代码可以注释保留,或者选择删除


7、添加职工


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


7.1 功能分析

分析:


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


如果想将所有不同种类的员工都放入到一个数组中,可以将所有员工的指针维护到一个数组里


如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护

5.png

7.2 功能实现

在WokerManager.h头文件中添加成员属性 代码:

//记录文件中的人数个数
  int m_EmpNum;
  //员工数组的指针
  Worker ** m_EmpArray;

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


WorkerManager::WorkerManager()
{
  //初始化人数
  this->m_EmpNum = 0;
  //初始化数组指针
  this->m_EmpArray = NULL;
}
在workerManager.h中添加成员函数
  //增加职工
  void Add_Emp();
workerManager.cpp中实现该函数
//增加职工
void WorkerManager::Add_Emp()
{
  cout << "请输入增加职工数量: " << endl;
  int addNum = 0;
  cin >> addNum;
  if (addNum > 0)
  {
  //计算新空间大小
  int newSize = this->m_EmpNum + addNum;
  //开辟新空间
  Worker ** newSpace = new Worker*[newSize];
  //将原空间下内容存放到新空间下
  if (this->m_EmpArray != NULL)
  {
    for (int i = 0; i < this->m_EmpNum; i++)
    {
    newSpace[i] = this->m_EmpArray[i];
    }
  }
  //输入新数据
  for (int i = 0; i < addNum; i++)
  {
    int id;
    string name;
    int dSelect;
    cout << "请输入第 " << i + 1 << " 个新职工编号:" << endl;
    cin >> id;
    cout << "请输入第 " << i + 1 << " 个新职工姓名:" << endl;
    cin >> name;
    cout << "请选择该职工的岗位:" << endl;
    cout << "1、普通职工" << endl;
    cout << "2、经理" << endl;
    cout << "3、老板" << endl;
    cin >> dSelect;
    Worker * worker = NULL;
    switch (dSelect)
    {
    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;
    }
    newSpace[this->m_EmpNum + i] = worker;
  }
  //释放原有空间
  delete[] this->m_EmpArray;
  //更改新空间的指向
  this->m_EmpArray = newSpace;
  //更新新的个数
  this->m_EmpNum = newSize;
  //提示信息
  cout << "成功添加" << addNum << "名新职工!" << endl;
  }
  else
  {
  cout << "输入有误" << endl;
  }
  system("pause");
  system("cls");
}
在WorkerManager.cpp的析构函数中,释放堆区数据
WorkerManager::~WorkerManager()
{
  if (this->m_EmpArray != NULL)
  {
  delete[] this->m_EmpArray;
  }
}


7.3 测试添加

在main函数分支 1 选项中,调用添加职工接口

6.png

效果如图:

7.png



至此,添加职工到程序中功能实现完毕


8、文件交互 - 写文件


功能描述:对文件进行读写


在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了


因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作


8.1 设定文件路径

首先我们将文件路径,在workerManager.h中添加宏常量,并且包含头文件 fstream

#include <fstream>
#define  FILENAME "empFile.txt"

8.2 成员函数声明

在workerManager.h中类里添加成员函数 void save()

//保存文件
void save();

8.3 保存文件功能实现

void WorkerManager::save()
{
  ofstream ofs;
  ofs.open(FILENAME, ios::out);
  for (int i = 0; i < this->m_EmpNum; i++)
  {
  ofs << this->m_EmpArray[i]->m_Id << " " 
    << this->m_EmpArray[i]->m_Name << " " 
    << this->m_EmpArray[i]->m_DeptId << endl;
  }
  ofs.close();
}


8.4 保存文件功能测试

在添加职工功能中添加成功后添加保存文件函数

8.png

再次运行代码,添加职工

9.png

同级目录下多出文件,并且保存了添加的信息

10.png

9、文件交互 - 读文件


功能描述:将文件中的内容读取到程序中


虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中


而我们的程序功能中还有清空文件的需求


因此构造函数初始化数据的情况分为三种


第一次使用,文件未创建

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

文件存在,并且保存职工的所有数据


9.1 文件未创建

在workerManager.h中添加新的成员属性 m_FileIsEmpty标志文件是否为空


//标志文件是否为空
  bool m_FileIsEmpty;

修改WorkerManager.cpp中构造函数代码


WorkerManager::WorkerManager()
{
  ifstream ifs;
  ifs.open(FILENAME, ios::in);
  //文件不存在情况
  if (!ifs.is_open())
  {
  cout << "文件不存在" << endl; //测试输出
  this->m_EmpNum = 0;  //初始化人数
  this->m_FileIsEmpty = true; //初始化文件为空标志
  this->m_EmpArray = NULL; //初始化数组
  ifs.close(); //关闭文件
  return;
  }
}


删除文件后,测试文件不存在时初始化数据功能


9.2 文件存在且数据为空

在workerManager.cpp中的构造函数追加代码:


//文件存在,并且没有记录
  char ch;
  ifs >> ch;
  if (ifs.eof())
  {
  cout << "文件为空!" << endl;
  this->m_EmpNum = 0;
  this->m_FileIsEmpty = true;
  this->m_EmpArray = NULL;
  ifs.close();
  return;
  }

追加代码位置如图:

11.png

将文件创建后清空文件内容,并测试该情况下初始化功能


我们发现文件不存在或者为空清空 m_FileIsEmpty 判断文件是否为空的标志都为真,那何时为假?


成功添加职工后,应该更改文件不为空的标志


在void WorkerManager::Add_Emp() 成员函数中添加:

//更新职工不为空标志
  this->m_FileIsEmpty = false;

12.png

9.3 文件存在且保存职工数据

9.3.1 获取记录的职工人数


在workerManager.h中添加成员函数 int get_EmpNum();


//统计人数
  int get_EmpNum();
workerManager.cpp中实现
int WorkerManager::get_EmpNum()
{
  ifstream ifs;
  ifs.open(FILENAME, ios::in);
  int id;
  string name;
  int dId;
  int num = 0;
  while (ifs >> id && ifs >> name && ifs >> dId)
  {
        //记录人数
  num++;
  }
  ifs.close();
  return num;
}

在workerManager.cpp构造函数中继续追加代码:

int num =  this->get_EmpNum();
  cout << "职工个数为:" << num << endl;  //测试代码
  this->m_EmpNum = num;  //更新成员属性

手动添加一些职工数据,测试获取职工数量函数

13.png14.png

9.3.2 初始化数组


根据职工的数据以及职工数据,初始化workerManager中的Worker ** m_EmpArray 指针


在WorkerManager.h中添加成员函数 void init_Emp();


//初始化员工
  void init_Emp();
在WorkerManager.cpp中实现
void WorkerManager::init_Emp()
{
  ifstream ifs;
  ifs.open(FILENAME, ios::in);
  int id;
  string name;
  int dId;
  int index = 0;
  while (ifs >> id && ifs >> name && ifs >> dId)
  {
  Worker * worker = NULL;
  //根据不同的部门Id创建不同对象
  if (dId == 1)  // 1普通员工
  {
    worker = new Employee(id, name, dId);
  }
  else if (dId == 2) //2经理
  {
    worker = new Manager(id, name, dId);
  }
  else //总裁
  {
    worker = new Boss(id, name, dId);
  }
  //存放在数组中
  this->m_EmpArray[index] = worker;
  index++;
  }
}

在workerManager.cpp构造函数中追加代码

//根据职工数创建数组
  this->m_EmpArray = new Worker *[this->m_EmpNum];
  //初始化职工
  init_Emp();
  //测试代码
  for (int i = 0; i < m_EmpNum; i++)
  {
  cout << "职工号: " << this->m_EmpArray[i]->m_Id
    << " 职工姓名: " << this->m_EmpArray[i]->m_Name
    << " 部门编号: " << this->m_EmpArray[i]->m_DeptId << endl;
  }

运行程序,测试从文件中获取的数据

15.png

至此初始化数据功能完毕,测试代码可以注释或删除掉!


10、显示职工


功能描述:显示当前所有职工信息


10.1 显示职工函数声明


在workerManager.h中添加成员函数 void Show_Emp();


//显示职工
  void Show_Emp();

10.2 显示职工函数实现


在workerManager.cpp中实现成员函数 void Show_Emp();


//显示职工
void WorkerManager::Show_Emp()
{
  if (this->m_FileIsEmpty)
  {
  cout << "文件不存在或记录为空!" << endl;
  }
  else
  {
  for (int i = 0; i < m_EmpNum; i++)
  {
    //利用多态调用接口
    this->m_EmpArray[i]->showInfo();
  }
  }
  system("pause");
  system("cls");
}

10.3 测试显示职工


在main函数分支 2 选项中,调用显示职工接口

16.png

测试时分别测试 文件为空和文件不为空两种情况


测试效果:


测试1-文件不存在或者为空情况

17.png

测试2 - 文件存在且有记录情况

18.png


测试完毕,至此,显示所有职工信息功能实现


相关文章
|
关系型数据库 MySQL 数据库
MySQL数据库期末项目 图书馆管理系统(上)
MySQL数据库期末项目 图书馆管理系统
239 0
|
1月前
|
存储 数据可视化 C++
【C++】C++ 职工信息管理系统(源码)【独一无二】
【C++】C++ 职工信息管理系统(源码)【独一无二】
|
10月前
|
存储 关系型数据库 MySQL
数据库原理与应用课程设计报告-工资管理系统
数据库原理与应用课程设计报告-工资管理系统
325 0
|
SQL 数据管理 Java
C#宿舍管理系统(C#课程设计含源码)
C#宿舍管理系统(C#课程设计含源码)
131 0
C#宿舍管理系统(C#课程设计含源码)
|
存储 Java 关系型数据库
JavaWeb期末项目 图书馆管理系统
JavaWeb期末项目 图书馆管理系统
150 1
|
存储 C++
C++职工管理系统(课程设计报告(三)
C++职工管理系统(课程设计报告(三)
|
4月前
|
设计模式
03——驾校科目一考试系统——登录界面(2)
运行项目——成功添加背景图 缺点:背景图片盖住了登录界面。
92 2
|
4月前
|
设计模式 数据安全/隐私保护
03——驾校科目一考试系统——登录界面(1)
双击ui文件进入设计模式。 想要把我们的登录窗口做成什么样的效果呢?理想效果图如下所示:用户需要一个账号和密码输入。最后还需要给用户两个按钮:一个登录按钮,一个取消按钮。
95 2
|
存储 关系型数据库 MySQL
MySQL数据库期末项目 图书馆管理系统(下)
MySQL数据库期末项目 图书馆管理系统(下)
94 0
|
4月前
|
设计模式 编译器 C语言