C++项目之 员工信息管理系统(8.2)

员工管理项目开发日志

Day 1: 类的设计
1.工作内容:

(1) 需求分析:

设计一个客户端软件,利用文件处理方式实现对公司人员进行管理,具有增加数据、更新数据、查询数据、删除数据以及文件读写的功能。员工信息包括:工号、姓名、年龄、岗位(岗位分为三种:销售员Salesman、销售经理SalesManager经理Manager)、销售额(Manager没有这个指标)

(2) 类的设计与要求:

类的设计要求:利用抽象类定义好接口,利用继承做好代码的复用。

(3) 用户接口设计:

要求给用户提供一个统一的接口来实现具体的管理功能(只给用户提供一个函数来使用,在这个函数中让用户选择数字标号代表的功能,再调用对应的函数实现对应的功能),让用户选择具体功能完成对应操作(对员工数据的增删改查)。

(4) 小组作业:

首先,通过小组讨论,主要对项目中所要用的类和可能用到的功能进行了分析,汇总得到以下内容,设置了抽象类 empployee,以及纯虚函数chang()和display()来修改和展示员工信息,还设置子类以及继承方式。

2.问题与解决方案

问题1: 所用到的类较少,没有考虑到将操作功能,操作的界面以及文件的输入输出写成类, 问题2: 在容器的选择上,组员提出了vector< set >嵌套的想法,但是可行度低,没有实际意义, 这种嵌套结构并不能很好地处理数据。 问题3:在容器中计划存放对象,但是考虑到体现多态性,在容器中应该存放指针,存放的空间也 需要考虑到。

解决方案: (1)基于类的思想,添加了操作类,界面操作类,以及文件IO类,通过类来实现管理系统

(2)数据的处理方面,通过vector容器来存放,在容器中存放父类指针,实现多态性,此外把数 据存放在堆空间里面,并进行空间的回收与释放。

Day 2: 项目框架代码实现
1.工作内容:

通过小组合作,在前一天的设计上对员工信息管理系统进行代码实现,每个组员写一 一个类,并由组长进行合并与类之间的连接,在功能的设计方面,安排两名组员来写文件的读写 功能,其他组员分别负责员工信息的修改,添加,以及标记待解雇,删除标记人员的功能的实现。 (1)父类和子类的部分代码如下

#pragma once
#include<iostream>
using namespace std;
//员工类,基类
class Employee {
protected:
    int m_ID;//工号
    string m_Name;//姓名
    int m_Age;//年龄
    string m_Position;//岗位
    string m_Status;//状态
public:
    Employee(int id, string name, int age, string position, string status)
        : m_ID(id), m_Name(name), m_Age(age), m_Position(position), m_Status(status) {
    }
    virtual  ~Employee()=default;
    // 虚函数,用于显示员工信息
    virtual void display() const = 0;
    virtual void change() = 0;
    virtual string toFileString() const = 0;
    int getId() const { return m_ID; }
    string getName() const { return m_Name; }
    int  getAge() const { return m_Age; }
    string getStatus() const { return m_Status; }   
};
#pragma once
#include"employee.h"
#include<iostream>
#include<string>
#include <iomanip> 
class Salesman :public Employee
{
protected:
    double m_Sales;
public:
    // 正确构造函数:初始化基类+派生类特有成员
    Salesman(int id, string name, int age, string position, string status, double sales)
        : Employee(id, name, age, position, status),  // 必须调用基类构造函数
        m_Sales(sales)  // 初始化派生类特有成员
    {
    }
    virtual~Salesman() {}
    int getId()const
    {
        return m_ID;
    }
    string getStatus() const { return m_Status; }
    virtual void display() const override {
        cout << setw(4) << left << m_ID
            << setw(8) << left << m_Name
            << setw(6) << left << m_Age
            << setw(9) << left << m_Position
            << setw(8) << left << m_Status
            << setw(10) << left << m_Sales << endl;  // 显示销售额
    }
    virtual void  change(){
        cout << "=====修改销售员信息=====" << endl;
        int num;
        cout << "请输入想要改变的信息:1姓名, 2年龄,3销售额 ,4岗位状态" << endl;
        cin >> num;
        switch (num) {
        case(1):
            cout << "请输入新姓名:";
            cin >> m_Name; // 直接修改基类的protected成员
            break;
        case(2):
            cout << "请输入年龄:";
            cin >> m_Age; // 直接修改基类的protected成员
            break;
        case(3):
            cout << "请输入新销售额:";
            cin >> m_Sales; // 直接修改基类的protected成员
            break;
    
        case(4):
            cout << "请输入新岗位状态:";
            cin >> m_Status; // 直接修改基类的protected成员
            break;
        case(0):break;
​
        default:
            cout << "输入错误!请输入1-4的整数。" << endl;
            break;
        }
    };
    string toFileString() const override {
        // 格式:工号,姓名,年龄,岗位,状态,工资(字段用逗号分隔,便于读取时拆分)
        return to_string(m_ID) + ","
            + m_Name + ","
            + to_string(m_Age) + ","
            + m_Position + ","
            + m_Status + ","
            + to_string(m_Sales);
    }
};

(2)部分关键功能设计如下: 修改员工信息的方法,主要通过父类指针去调用子类方法来实现,这里采用auto自动推导类型,更加方便处理,展示员工信息的方法也是基于此种方法实现的。

//方法4:修改员工信息的入口方法
void changeInf() {
  
    // 修改员工信息的入口方法
​
    int targetId;
    cout << "请输入要修改的员工工号:";
    cin >> targetId;
​
    // 遍历容器查找目标员工
    for (auto emp : v) {
        if (emp->getId() == targetId)
        { // 调用基类的getId()方法
            emp->change(); // 多态c调用:自动执行对应子类的updateInfo()
            cout << "修改已完成";
            return; // 找到后立即返回
​
        }
    }
    // 若遍历完未找到
    cout << "未找到工号为 " << targetId << " 的员工!" << endl;
​
}
2.问题与解决方案:

第二天的主要问题在功能的设计上,在设计员工信息的修改时候,若修改员工的职位,则会改变员工的类别,因此需要重新创建一个类对象,把创建后的新的覆盖原来的对象,以及其他功能或设计的细节上的考虑。

解决方案:功能的重新设计与细节的添加

void changePos() {
    cout << "请输入要修改职位的员工工号:" << endl;
    int target, type;
    cin >> target;
​
    // 遍历容器查找目标员工(用迭代器便于删除)
    auto it = v.begin();
    bool found = false;
    while (it != v.end()) {
        if ((*it)->getId() == target) {
            found = true;
            // 1. 保存原员工信息
            Employee* oldEmp = *it;
            string name = oldEmp->getName();  //将原来的数据取出来 准备给新对象
            int age = oldEmp->getAge();       // 需 Employee 有 getAge()
            string status = oldEmp->getStatus();  // 需 Employee 有 getStatus()
​
            // 2. 输入新职位类型
            cout << "请输入想修改的职位:1.销售员 2.销售经理 3.经理" << endl;
            cin >> type;
​
            // 3. 根据类型创建新职位对象(替换原对象)
            Employee* newEmp = nullptr;
            switch (type) {
            case 1:
                newEmp = new Salesman(target, name, age, "销售员", status, 0);
                break;  // 添加 break 防止穿透
            case 2:
                newEmp = new SaleManager(target, name, age, "销售经理", status, 0);
                break;
            case 3:
                newEmp = new Manager(target, name, age, "经理", status);
      
                break;
            default:
                cout << "输入错误!请输入1-3的整数。" << endl;
                return;  // 输入错误时直接退出,不修改
            }
​
            // 4. 替换容器中的元素(删除原对象,添加新对象)
            delete oldEmp;  // 释放原对象内存,避免泄漏
            *it = newEmp;   // 用新对象替换原位置的指针
            cout << "职位修改成功!" << endl;
            return;  // 完成后退出函数
        }
        ++it;
    }

在经理类的change()函数中,不提供修改销售额的功能,而其他两个子类正常提供

virtual void change()
{
    cout << "=====修改经理信息=====" << endl;
    int num;
    cout << "请输入想要改变的信息:1姓名, 2年龄 ,3岗位状态";
    cin >> num;
    switch (num) {
    case(1):
        cout << "请输入新姓名:";
        cin >> m_Name; // 直接修改基类的protected成员
        break;
    case(2):
        cout << "请输入年龄:";
        cin >> m_Age; // 直接修改基类的protected成员
       break;
    case(3):
        cout << "请输入新岗位状态:";
        cin >> m_Status; // 直接修改基类的protected成员
        break;
    case(0):break;
    default:
        cout << "输入错误!请输入1-4的整数。" << endl;
    }
}

Day3 :项目优化与展示
1.工作内容:

基于昨天发现的问题,在改进项目后通过多次对信息管理系统各功能的模拟,发现其中的bug并进行优化项目,部分功能展示如下

2.问题与解决方案:

(1) 在界面操作类里面出现了一些小bug,比如输入功能标号,与实际出现的功能不一致的情况, 其次在操作的时候,输入员工职位或者状态这些文字内容时,考虑到实际操作的情况,应该采用 一些标号来替代文字方便用户操作。

(2) 在验证方面,由于会出现一些错误输入,所以应该考虑到这些异常的情况,设置一些错误提示或者异常处理。

解决方案:对信息管理的各种操作进行优化,并且参考其他小组的项目优势,加到自己的项目里面。

(1) 添加表头

(2)添加各种错误验证:

(3)用数字代替职位和状态的输入,方便用户操作

项目总结

作为学习C++基础后的第一个小型项目,这种信息管理系统既能用到之前学习的C++基础,又能很好地通过类的运用和容器的结合,让新手能够串联起C++基础阶段学到的各种知识,再通过分析各种bug和优化自己的项目,来提升自己的语言思想与代码能力,毕竟眼过千遍,不如手过一遍。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值