@[TOC](文章目录)

题目

设计一个职工信息管理案例,实现不同类别职工的工资数据。职工的种类包括: 正式职工和临时工。 定义一个基本的职工类,基本信息包括:姓名name、基本职务工资basicSalary 派生出正式职工类,增加的属性包括:所得税tax、实发工资realSalary 临时工增加的属性包括:奖金bonus、实发工资realSalary

  1. 正式职工:实发工资realSalary = 基本职务工资basicSalary - 所得税tax;
  2. 临时工: 实发工资realSalary = 基本职务工资basicSalary + 奖金bonus;

基本功能与技术要求: 1、数据文件管理功能:利用输入输出流创建新文件、打开文件、保存文件。 2、计算与统计功能:采用静态数据成员与成员函数完成记录中相关数据的统计; (1) 能够打开已存在的数据表文件, 对数据表中与某关键字匹配的相关记录进行数据统计(包括:每种职工人数、工资总额、平均值) (2) 计算每个职工的实发工资。 3、记录管理功能:利用继承与派生思想创建不同的类;记录的管理采用链表或者指针数组 实现;采用抽象类、虚函数等实现对象与函数的动态关联,体现多态性。 (1)输入/添加/插入记录:利用重载运算符“>>”完成对任意一条记录输入、添加或插入数据表中,并保存到数据文件中。 (2)查询、显示记录:能够打开已存在的数据表文件,根据用户要求按所给记录关键字查询一个或多个相关联记录的各项信息。利用重载运算符“<<”输出一个对象的信息。 (3)修改记录:能够打开已存在的数据表文件,并对确定的任意记录进行修改,在修改过程中,应显示记录信息,给出确认提示,并对更新的记录信息进行文件保存。 (4)删除记录:能够打开已存在的数据表文件,可以删除数据表中的任一记录,要求具备逻辑删除(具有恢复功能)和物理删除功能,并对新的数据表信息进行文件保存。 (我的思路: 在Worker类中添加一个属性flag; 其中0表示不可访问, 1表示可访问, 这样就实现了两种删除的功能)

github网址

https://github.com/deng1604/Worker


<!--

主函数

#include <iostream>
#include <string>
#include <vector>
#include "Worker.h"
#include "FormalWorker.h"
#include "TempWorker.h"
using namespace std;

const int MAX_SIZE = 100;                                     // 职工的最大人数

void myMenu();                                                // 提示菜单
void input(vector<Worker*>& pWorker, int num);                // 输入职工信息          (一定要记得加引用&符号)
void output(vector<Worker*>& pWorker, int num);               // 输出职工信息 
void queryWorkerByName(vector<Worker*>& pWorker, int num);    // 根据姓名来查找职工信息
void modifyWorkerByName(vector<Worker*>& pWorker, int num);   // 根据姓名来修改职工信息
void deleteWorkerByName(vector<Worker*>& pWorker, int num);   // 根据姓名来删除职工信息 (可恢复)
void clearWorkerByName(vector<Worker*>& pWorker, int& num);   // 根据姓名来删除职工信息 (不可恢复)
void recoverWorkerByName(vector<Worker*>& pWorker, int num);  // 根据姓名来恢复一个职工信息
void deleteAllWorker(vector<Worker*>& pWorker, int num);      // 用循环来删除指针数组
void showWorkerNum(vector<Worker*>& pWorker, int num);        // 显示各种职工的人数
void showWorkerSalary(vector<Worker*>& pWorker, int num);     // 显示职工总的实发工资、平均实发工资

int main()
{
    int num;
    cout << "请输入职工的人数: ";
    cin >> num;

    vector<Worker*> pWorker(num);   // 相当于Worker* pWorker[num];

    input(pWorker, num);

    myMenu();

    int choice;
    while (true)
    {
        cout << "\n\n------------------------------------------------";
        cout << "\n请输入您的选择(0-10): ";
        cin >> choice;
        switch (choice)
        {
        case 1:
            input(pWorker, num);
            break;
        case 2:
            deleteWorkerByName(pWorker, num);
            break;
        case 3:
            modifyWorkerByName(pWorker, num);
            break;
        case 4:
            queryWorkerByName(pWorker, num);
            break;
        case 5:
            clearWorkerByName(pWorker, num);
            break;
        case 6:
            recoverWorkerByName(pWorker, num);
            break;
        case 7:
            output(pWorker, num);
            break;
        case 8:
            myMenu();
            break;
        case 9:
            showWorkerNum(pWorker, num);
            break;
        case 10:
            showWorkerSalary(pWorker, num);
            break;
        case 0:
            deleteAllWorker(pWorker, num);
            cout << "成功退出系统。byebye" << endl;
            return 0; // 退出程序
        default:
            cout << "您的输入有误, 请重新输入0-10之间的数。" << endl;
            break;
        }
    }

    return 0;
}

/* 提示菜单 */
void myMenu()
{
    cout << endl << endl;
    cout << "----------------------菜  单-------------------------------" << endl;
    cout << "     1 增加职工记录             2 删除职工记录 (可恢复)      " << endl;
    cout << "     3 修改职工记录             4 查找职工记录              " << endl;
    cout << "     5 删除职工记录 (不可恢复)  6 恢复职工数据               " << endl;
    cout << "     7 显示职工记录             8 显示菜单                  " << endl;
    cout << "     9 统计职工人数              10 统计职工工资             " << endl;
    cout << "     0 退出系统                                             " << endl;
    cout << "-----------------------------------------------------------" << endl;
}

/* 输入职工信息 */
void input(vector<Worker*>& pWorker, int num)           // 相当于void input(Worker* pWorker[], int num)    
{
    string name;        // 姓名
    double basicSalary; // 基本工资
    double tax;         // 所得税
    double bonus;       // 奖金
    char choice;

    cout << "请输入职工类型 t是临时工、f是正式职工: \n" << endl;

    for (int i = 0; i < num; i++)
    {
        cin >> choice;
        if (choice == 'f' || choice == 'F')
        {
            cin >> name >> basicSalary >> tax;
            //FormalWorker fWorker(name, basicSalary, tax); 
            //pWorker[i] = &fWorker;    // 不行: 在循环内创建对象, 循环结束后会调用析构函数, 无法统计个数
            pWorker[i] = new FormalWorker(name, basicSalary, tax);
            pWorker[i]->showCount();
            pWorker[i]->showSalary();
        }
        else if (choice == 't' || choice == 'T')
        {
            cin >> name >> basicSalary >> bonus;
            pWorker[i] = new TempWorker(name, basicSalary, bonus);
            pWorker[i]->showCount();
            pWorker[i]->showSalary();
        }
        else
        {
            cout << "您的输入有误!!!" << endl;
            pWorker[i] = new TempWorker();     // 调用无参构造函数, 防止有部分pWorker[i]未初始化而不好delete ? 
        }
        pWorker[i]->flag = true;   // 表示可以访问
    }
}

/* 输出职工信息 */
void output(vector<Worker*>& pWorker, int num)
{
    cout << endl << endl;
    cout << "姓名  基本工资 税/奖金 实发工资" << endl;
    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)                            // ------------------------------------------------
        {
            //pWorker[i]->show();                        // (是可以正常运行的, 不过题目要求用重载运算符)    
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                cout << *p1;
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                cout << *p2;
            }
            else
            {
                cout << "OUTPUT ERROR!!!" << endl;
                exit(1);
            }
        }
    }
}

/* 根据姓名来查找职工信息 */
void queryWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要查询的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag)
        {
            cout << "姓名为: " << queryName << ", 基本工资是: " << pWorker[i]->getBasicSalary() << endl;
            return; // 查找成功
        }
    }

    cout << "查找失败 !!!" << endl;
}

/* 根据姓名来修改职工信息: (备注, 这里只修改了姓名) */
void modifyWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName, newName;
    cout << "\n请输入要修改的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag)              // 查找成功
        {
            cout << "请输入要修改新名字: " << endl;
            cin >> newName;
            pWorker[i]->setName(newName);
            return; // 查找成功, 返回
        }
    }

    cout << "查找失败, 姓名无法修改!" << endl;
}

/* 根据姓名来删除职工信息 (可恢复) */
void deleteWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要删除的职工的姓名(可恢复): " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName)  // 查找成功
        {
            pWorker[i]->flag = false;            // 设置为不可访问
            return;                              // 查找成功, 返回
        }
    }

    cout << "查无此人, 无法删除!" << endl;
}

/* 根据姓名来删除职工信息 (不可恢复) */
void clearWorkerByName(vector<Worker*>& pWorker, int& num)
{
    string queryName;
    cout << "\n请输入要删除的职工的姓名(不可恢复): " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName)    // 查找成功
        {
            delete pWorker[i];                     // 先释放该元素空间 (原因:必须要在erase之前将其delete掉)
            pWorker.erase(pWorker.begin() + i);    // 删除pWorker[i]元素
            num--;
            return;                                // 查找成功, 返回
        }
    }

    cout << "查无此人, 无法删除!" << endl;
}

/* 根据姓名来恢复一个职工信息 */
void recoverWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要恢复的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag == false)
        {
            pWorker[i]->flag = true;
            cout << "恢复成功: " << endl;
            return;            // 查找成功, 返回
        }
    }

    cout << "查无此人, 恢复失败!" << endl;
}

/* 9.显示各种职工人数 */
void showWorkerNum(vector<Worker*>& pWorker, int num)
{
    /*
    TempWorker::showCount();    // 不行! 
    FormalWorker::showCount();  // 原因: 可恢复删除(未delete)导致人数没有变化 !!!!!!!!!!!!!!!!!
    */

    int formalWorkerNum = 0;
    int tempWorkerNum = 0;
    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)
        {
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                formalWorkerNum++;
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                tempWorkerNum++;
            }
            else
            {
                cout << "SHOWWORKERNUM ERROR!!!" << endl;
                exit(1);
            }
        }
    }
    cout << "临时职工的总人数为: " << tempWorkerNum << endl;
    cout << "正式职工的总人数为: " << formalWorkerNum << endl;
}

/* 显示职工总的实发工资、平均实发工资 */
void showWorkerSalary(vector<Worker*>& pWorker, int num)
{
    /*
    TempWorker::showSalary();    // 不行
    FormalWorker::showSalary();  // 原因: 可恢复删除(未delete)导致静态的人数没有变化 !!!!!!!!!!!!!!!!!
    */

    int formalWorkerNum = 0;
    int tempWorkerNum = 0;
    double formalWorkerSalary = 0;
    double tempWorkerSalary = 0;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)
        {
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                formalWorkerNum++;
                formalWorkerSalary += p1->getRealSalary();
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                tempWorkerNum++;
                tempWorkerSalary += p2->getRealSalary();
            }
            else
            {
                cout << "SHOWWORKERSALARY ERROR!!!" << endl;
                exit(1);
            }
        }
    }
    cout << "临时职工的总实发工资为:  " << tempWorkerSalary << endl;
    cout << "临时职工的平均实发工资为: " << tempWorkerSalary / tempWorkerNum << endl;

    cout << "正式职工的总实发工资为:  " << formalWorkerSalary << endl;
    cout << "正式职工的平均实发工资为: " << formalWorkerSalary / formalWorkerNum << endl;
}

/* 用循环来删除指针数组 (new和delete必须要同时使用) */
void deleteAllWorker(vector<Worker*>& pWorker, int num)
{
    for (int i = 0; i < num; i++)
    {
        delete pWorker[i];
    }
}

/*
测试数据:
10
f 小明 10000 900
F 张三 3000 800
f 李四 4000 700
f 王五 5000 600
F 赵六 6000 500
T AAA 10000 900
t BBB 3000 800
T CCC 4000 700
t DDD 5000 600
t EEE 6000 500
4
王五
7
3
小明
小二
7
8
5
赵六
7
2
BBB
7
6
赵六
6
BBB
7
9
8
2
DD
2
DDD
7
9
10
0
*/

/**
 * 备注:
 * 1.这个程序的静态的统计人数不好写, 主要是因为可恢复删除那里, 删除时未调用析构函数, 导致统计出错
 *   我暂时先: 遍历pWorker数组, 运用dynamic_cast动态类型转换来求出具体人数
 * 
 * 2.那个静态的统计分数和平均分的函数呢? 
 *   该怎么写呀???
 * 
 * 3.复制构造函数有什么用处呢?
 * 
 */

-->

Worker.h

#pragma once         // 防止头文件重复包含
#include <string>
using namespace std;

class Worker
{
private:
    string name;         // 姓名
    double basicSalary;  // 基本职务工资
public:
    bool flag;           // 0表示不可访问, 1表示可访问

    Worker();
    Worker(string name, double basicSalary);
    virtual ~Worker();

    double getBasicSalary();
    string getName();
    void setName(string name);
    //void setBasicSalary(double basicSalary);

    virtual void show();
    virtual void showCount();    // 这里不能加上static, 因为: 仅非静态成员函数是可以虚拟的
    virtual void showSalary();   // 这里不能加上static, 因为: 仅非静态成员函数是可以虚拟的
};

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, Worker& w);

Worker.cpp

#include <iostream>
#include "Worker.h"
using namespace std;

Worker::Worker()
{
    this->name = "无名氏";
    this->basicSalary = 0;
}

Worker::Worker(string name, double basicSalary)
{
    this->name = name;
    this->basicSalary = basicSalary;
}

Worker::~Worker() {
}

double Worker::getBasicSalary()
{
    return basicSalary;
}

string Worker::getName()
{
    return name;
}

void Worker::setName(string name)
{
    this->name = name;
}

/* 抽象函数: 输出对应职工的属性 */
void Worker::show() {
}

/* 抽象函数: 输出对应职工的人数 */ 
void Worker::showCount() {
}

/* 抽象函数: 输出对应职工的总工资、平均工资 */
void Worker::showSalary(){
}

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, Worker& w)
{
    cout << w.getName() << "\t" << w.getBasicSalary() << endl;
    return cout;
}

TempWorker.h

#pragma once
#include "Worker.h"

class TempWorker : public Worker
{
private:
    double bonus;               // 奖金
    double realSalary;          // 实发工资
    static int tempCount;       // 静态数据类型: 临时工总人数 (只是声明, 另外还需要在cpp文件中定义 !!!)
    static double totalSalary;  // 静态数据类型: 临时工总工资
public:
    TempWorker();
    TempWorker(string name, double basicSalary, double bonus);
    virtual ~TempWorker();

    double getBonus();         // 获取临时工的奖金
    double getRealSalary();    // 获得临时工的实发工资

    void show();               // 输出临时工的姓名、基本工资、所得税、实发工资
    static void showCount();   // 输出临时工的总数
    static void showSalary();  // 输出临时工的总工资、平均工资
}; 

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, TempWorker& t);

TempWorker.cpp

#include <iostream>
#include "TempWorker.h"
using namespace std;

/* 临时工的人数赋初值为0 (定义) */
int TempWorker::tempCount = 0;

/* 临时工的总工资赋初值为0 (定义) */
double TempWorker::totalSalary = 0;

TempWorker::TempWorker()
{
    this->bonus = 0;
    this->realSalary = getBasicSalary();
    tempCount++;               // 临时工个数加1
    totalSalary += 0;
}

/* 注意: 子类的有参构造函数中, 一定要给父类的属性赋值 */
TempWorker::TempWorker(string name, double basicSalary, double bonus) : Worker(name, basicSalary)
{
    this->bonus = bonus;
    this->realSalary = getBasicSalary() + bonus;
    tempCount++;
    totalSalary += realSalary;
}

TempWorker::~TempWorker()
{
    tempCount--;               // 临时工个数减1
    totalSalary -= realSalary;
}

/* 获得临时职工的实发工资 */
double TempWorker::getBonus()
{
    return bonus;
}

/* 获得临时职工的实发工资 */
double TempWorker::getRealSalary()
{
    return realSalary;
}

/* 输出临时职工的姓名、基本工资、所得税、实发工资 */
void TempWorker::show()
{
    cout << getName() << "\t" << getBasicSalary() << "\t" << getBonus() << "\t" << getRealSalary() << endl;
}

/* 输出临时工的总数 */
void TempWorker::showCount()
{
    cout << "临时职工的总人数为: " << tempCount << endl;
}

/* 输出临时工的总工资、平均工资 */
void TempWorker::showSalary()
{
    cout << "临时职工的总工资为: " << totalSalary << endl;
    cout << "临时职工的平均工资为: " << totalSalary / tempCount << endl << endl;
}

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, TempWorker& t)
{
    cout << t.getName()  << "\t" << t.getBasicSalary() << "\t"
         << t.getBonus() << "\t" << t.getRealSalary() << endl;
    return cout;
}

FormalWorker.h

#pragma once        
#include "Worker.h"

class FormalWorker : public Worker
{
private:
    double tax;                 // 所得税
    double realSalary;          // 实发工资
    static int formalCount;     // 静态数据类型: 正式职工总人数   (只是声明, 另外还需要在cpp文件中定义 !!!)
    static double totalSalary;  // 静态数据类型: 正式职工总工资、平均工资
public:
    FormalWorker();
    FormalWorker(string name, double basicSalary, double tax);
    virtual ~FormalWorker();

    double getTax();
    double getRealSalary();

    void show();                // 输出正式职工的姓名、基本工资、所得税、实发工资
    static void showCount();    // 输出正式职工的总数
    static void showSalary();   // 输出正式职工的总工资、平均工资
};

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, FormalWorker& f);

FormalWorker.cpp

#include <iostream>
#include "FormalWorker.h"
using namespace std;

/* 临时工的人数赋初值为0 (定义) !!! */
int FormalWorker::formalCount = 0;

/* 临时工的总工资赋初值为0 (定义) */
double FormalWorker::totalSalary = 0;

FormalWorker::FormalWorker()
{
    this->tax = 0;
    this->realSalary = getBasicSalary();
    formalCount++;
    totalSalary += 0;
}

/* 注意: 子类的有参构造函数中, 一定要给父类的属性赋值 */
FormalWorker::FormalWorker(string name, double basicSalary, double tax) : Worker(name, basicSalary)
{
    this->tax = tax;
    this->realSalary = getBasicSalary() - tax;
    formalCount++;
    totalSalary += realSalary;
}

FormalWorker::~FormalWorker()
{
    formalCount--;
    totalSalary -= realSalary;
}

double FormalWorker::getRealSalary()
{
    return realSalary;
}

double FormalWorker::getTax()
{
    return tax;
}

/* 输出正式职工的姓名、基本工资、所得税、实发工资 */
void FormalWorker::show()
{
    cout << getName() << "\t" << getBasicSalary() << "\t" << getTax() << "\t" << getRealSalary() << endl;
}

/* 输出正式职工的总数 */
void FormalWorker::showCount()
{
    cout << "正式职工的总人数为: " << formalCount << endl;
}

/* 输出正式职工的总工资、平均工资 */
void FormalWorker::showSalary()
{
    cout << "正式职工的总工资为: " << totalSalary << endl;
    cout << "正式职工的平均工资为: " << totalSalary / formalCount << endl << endl;
}

/* 重载左移运算符 (用于输出一个对象的信息) */
ostream& operator<<(ostream& cout, FormalWorker& f)
{
    cout << f.getName() << "\t" << f.getBasicSalary() << "\t"
         << f.getTax()  << "\t" << f.getRealSalary()  << endl;
    return cout;
}

包含文件操作的主函数部分

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "Worker.h"
#include "FormalWorker.h"
#include "TempWorker.h"
using namespace std;

const int MAX_SIZE = 100;                                     // 职工的最大人数

void myMenu();                                                // 提示菜单
void input(vector<Worker*>& pWorker, int num);                // 输入职工信息          (一定要记得加引用&符号)
void output(vector<Worker*>& pWorker, int num);               // 输出职工信息 
void queryWorkerByName(vector<Worker*>& pWorker, int num);    // 根据姓名来查找职工信息
void modifyWorkerByName(vector<Worker*>& pWorker, int num);   // 根据姓名来修改职工信息
void deleteWorkerByName(vector<Worker*>& pWorker, int num);   // 根据姓名来删除职工信息 (可恢复)
void clearWorkerByName(vector<Worker*>& pWorker, int& num);   // 根据姓名来删除职工信息 (不可恢复)
void recoverWorkerByName(vector<Worker*>& pWorker, int num);  // 根据姓名来恢复一个职工信息
void deleteAllWorker(vector<Worker*>& pWorker, int num);      // 用循环来删除指针数组
void showWorkerNum(vector<Worker*>& pWorker, int num);        // 显示各种职工的人数
void showWorkerSalary(vector<Worker*>& pWorker, int num);     // 显示职工总的实发工资、平均实发工资
void saveToFile(vector<Worker*>& pWorker, int num);           // 将pWorker数字的内容保存到文件中 (覆盖原文件)
void showFile();                                              // 显示两个文件的内容 

int main()
{
    int num;
    cout << "请输入职工的人数: ";
    cin >> num;

    vector<Worker*> pWorker(num);   // 相当于Worker* pWorker[num];

    input(pWorker, num);

    myMenu();

    int choice;
    while (true)
    {
        cout << "\n\n------------------------------------------------";
        cout << "\n请输入您的选择(0-12): ";
        cin >> choice;
        switch (choice)
        {
        case 1:
            input(pWorker, num);
            break;
        case 2:
            deleteWorkerByName(pWorker, num);
            break;
        case 3:
            modifyWorkerByName(pWorker, num);
            break;
        case 4:
            queryWorkerByName(pWorker, num);
            break;
        case 5:
            clearWorkerByName(pWorker, num);
            break;
        case 6:
            recoverWorkerByName(pWorker, num);
            break;
        case 7:
            output(pWorker, num);
            break;
        case 8:
            myMenu();
            break;
        case 9:
            showWorkerNum(pWorker, num);
            break;
        case 10:
            showWorkerSalary(pWorker, num);
            break;
        case 11:
            saveToFile(pWorker, num);
            break;
        case 12:
            showFile();
            break;
        case 0:
            deleteAllWorker(pWorker, num);
            cout << "成功退出系统。byebye" << endl;
            return 0; // 退出程序
        default:
            cout << "您的输入有误, 请重新输入0-12之间的数。" << endl;
            break;
        }
    }

    return 0;
}

/* 提示菜单 */
void myMenu()
{
    cout << endl << endl;
    cout << "----------------------菜  单-------------------------------" << endl;
    cout << "     1 增加职工记录             2 删除职工记录 (可恢复)      " << endl;
    cout << "     3 修改职工记录             4 查找职工记录              " << endl;
    cout << "     5 删除职工记录 (不可恢复)  6 恢复职工数据               " << endl;
    cout << "     7 显示职工记录             8 显示菜单                  " << endl;
    cout << "     9 统计职工人数              10 统计职工工资             " << endl;
    cout << "     11 保存至文件               12 显示文件内容             " << endl;
    cout << "     0 退出系统                                             " << endl;
    cout << "-----------------------------------------------------------" << endl;
}

/* 输入职工信息 */
void input(vector<Worker*>& pWorker, int num)           // 相当于void input(Worker* pWorker[], int num)    
{
    string name;        // 姓名
    double basicSalary; // 基本工资
    double tax;         // 所得税
    double bonus;       // 奖金
    char choice;

    cout << "请输入职工类型 t是临时工、f是正式职工: \n" << endl;

    for (int i = 0; i < num; i++)
    {
        cin >> choice;
        if (choice == 'f' || choice == 'F')
        {
            cin >> name >> basicSalary >> tax;
            //FormalWorker fWorker(name, basicSalary, tax); 
            //pWorker[i] = &fWorker;    // 不行: 在循环内创建对象, 循环结束后会调用析构函数, 无法统计个数
            pWorker[i] = new FormalWorker(name, basicSalary, tax);
            pWorker[i]->showCount();
            pWorker[i]->showSalary();
        }
        else if (choice == 't' || choice == 'T')
        {
            cin >> name >> basicSalary >> bonus;
            pWorker[i] = new TempWorker(name, basicSalary, bonus);
            pWorker[i]->showCount();
            pWorker[i]->showSalary();
        }
        else
        {
            cout << "您的输入有误!!!" << endl;
            pWorker[i] = new TempWorker();     // 先调用无参构造函数, 防止有部分pWorker[i]未初始化而不好delete
        }
        pWorker[i]->flag = true;   // 表示可以访问
    }
}

/* 输出职工信息 */
void output(vector<Worker*>& pWorker, int num)
{
    cout << endl << endl;
    cout << "姓名  基本工资 税/奖金 实发工资" << endl;
    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)                            // ------------------------------------------------
        {
            //pWorker[i]->show();                        // (可以正常运行)    
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                cout << *p1;
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                cout << *p2;
            }
            else
            {
                cerr << "OUTPUT ERROR!!!" << endl;
                exit(1);
            }
        }
    }
}

/* 根据姓名来查找职工信息 */
void queryWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要查询的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag)
        {
            cout << "姓名为: " << queryName << ", 基本工资是: " << pWorker[i]->getBasicSalary() << endl;
            return; // 查找成功
        }
    }

    cout << "查找失败 !!!" << endl;
}

/* 根据姓名来修改职工信息: (备注, 这里只修改了姓名) */
void modifyWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName, newName;
    cout << "\n请输入要修改的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag)              // 查找成功
        {
            cout << "请输入要修改新名字: " << endl;
            cin >> newName;
            pWorker[i]->setName(newName);
            return; // 查找成功, 返回
        }
    }

    cout << "查找失败, 姓名无法修改!" << endl;
}

/* 根据姓名来删除职工信息 (可恢复) */
void deleteWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要删除的职工的姓名(可恢复): " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName)  // 查找成功
        {
            pWorker[i]->flag = false;            // 设置为不可访问
            return;                              // 查找成功, 返回
        }
    }

    cout << "查无此人, 无法删除!" << endl;
}

/* 根据姓名来删除职工信息 (不可恢复) */
void clearWorkerByName(vector<Worker*>& pWorker, int& num)
{
    string queryName;
    cout << "\n请输入要删除的职工的姓名(不可恢复): " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName)    // 查找成功
        {
            delete pWorker[i];                     // 先释放该元素空间 (原因:必须要在erase之前将其delete掉)
            pWorker.erase(pWorker.begin() + i);    // 删除pWorker[i]元素
            num--;
            return;                                // 查找成功, 返回
        }
    }

    cout << "查无此人, 无法删除!" << endl;
}

/* 根据姓名来恢复一个职工信息 */
void recoverWorkerByName(vector<Worker*>& pWorker, int num)
{
    string queryName;
    cout << "\n请输入要恢复的职工的姓名: " << endl;
    cin >> queryName;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->getName() == queryName && pWorker[i]->flag == false)
        {
            pWorker[i]->flag = true;
            cout << "恢复成功: " << endl;
            return;            // 查找成功, 返回
        }
    }

    cout << "查无此人, 恢复失败!" << endl;
}

/* 9.显示各种职工人数 */
void showWorkerNum(vector<Worker*>& pWorker, int num)
{
    /*
    TempWorker::showCount();    // 不行
    FormalWorker::showCount();  // 原因: 可恢复删除(未delete)导致静态的人数没有变化 !!!!!!!!!!!!!!!!!
    */

    int formalWorkerNum = 0;
    int tempWorkerNum = 0;
    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)
        {
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                formalWorkerNum++;
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                tempWorkerNum++;
            }
            else
            {
                cerr << "SHOWWORKERNUM ERROR!!!" << endl;
                exit(1);
            }
        }
    }
    cout << "临时职工的总人数为: " << tempWorkerNum << endl;
    cout << "正式职工的总人数为: " << formalWorkerNum << endl;
}

/* 显示职工总的实发工资、平均实发工资 */
void showWorkerSalary(vector<Worker*>& pWorker, int num)
{
    /*
    TempWorker::showSalary();    // 不行
    FormalWorker::showSalary();  // 原因: 可恢复删除(未delete)导致静态的人数没有变化 !!!!!!!!!!!!!!!!!
    */

    int formalWorkerNum = 0;
    int tempWorkerNum = 0;
    double formalWorkerSalary = 0;
    double tempWorkerSalary = 0;

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)
        {
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                // 转换成功, 是FormalWorker对象(正式职工)
            {
                formalWorkerNum++;
                formalWorkerSalary += p1->getRealSalary();
            }
            else if (p1 == NULL && p2 != NULL)           // 转换成功, 是TempWorker对象  (临时工)
            {
                tempWorkerNum++;
                tempWorkerSalary += p2->getRealSalary();
            }
            else
            {
                cerr << "SHOWWORKERSALARY ERROR!!!" << endl;
                exit(1);
            }
        }
    }
    cout << "临时职工的总实发工资为:  " << tempWorkerSalary << endl;
    cout << "临时职工的平均实发工资为: " << tempWorkerSalary / tempWorkerNum << endl;

    cout << "正式职工的总实发工资为:  " << formalWorkerSalary << endl;
    cout << "正式职工的平均实发工资为: " << formalWorkerSalary / formalWorkerNum << endl;
}

/* 用循环来删除指针数组 (new和delete必须要同时使用) */
void deleteAllWorker(vector<Worker*>& pWorker, int num)
{
    for (int i = 0; i < num; i++)
    {
        delete pWorker[i];
    }
}

/* 将pWorker数字的内容保存到文件中 (覆盖原文件) */
void saveToFile(vector<Worker*>& pWorker, int num)
{
    ofstream ofs;
    ofs.open("formalWorker.txt", ios::trunc); // 如果文件存在, 先删除, 再创建
    ofstream ofs2;
    ofs2.open("tempWorker.txt", ios::trunc);  

    for (int i = 0; i < num; i++)
    {
        if (pWorker[i]->flag)
        {
            FormalWorker* p1 = dynamic_cast<FormalWorker*>(pWorker[i]);
            TempWorker* p2 = dynamic_cast<TempWorker*>(pWorker[i]);
            if (p1 != NULL && p2 == NULL)                 // 正式职工
            {
                ofs << p1->getName() << "  " << p1->getBasicSalary() << "  " 
                    << p1->getTax() << "  " << p1->getRealSalary() << endl;
            }
            else if (p1 == NULL && p2 != NULL)            // 临时工
            {
                ofs2 << p2->getName() << "  " << p2->getBasicSalary() << "  "
                     << p2->getBonus() << "  " << p2->getRealSalary() << endl;
            }
            else
            {
                cerr << "saveToFile ERROR!!!" << endl;
                exit(1);
            }
        }
    }
    ofs.close();
    ofs2.close();
    cout << "保存成功..." << endl;
}

/* 显示两个文件的内容 */
void showFile()
{
    // 1.打开正式职工文件
    ifstream ifs;
    ifs.open("formalWorker.txt", ios::in);
    if (!ifs.is_open())
    {
        cerr << "formalWorker的文件打开失败" << endl;
    }
    else
    {
        cout << "\n正式职工文件打开成功: " << endl;
        cout << "姓名  基本工资 税 实发工资" << endl;
        string str;
        while (getline(ifs, str))
        {
            cout << str << endl;
        }
    }
    ifs.close();

    // 2.打开临时工文件
    ifstream ifs2;
    ifs2.open("tempWorker.txt", ios::in);
    if (!ifs2.is_open())
    {
        cerr << "tempWorker的文件打开失败" << endl;
    }
    else
    {
        cout << "\n临时职工文件打开成功: " << endl;
        cout << "姓名  基本工资 奖金 实发工资" << endl;
        string str;
        while (getline(ifs2, str))
        {
            cout << str << endl;
        }
    }
    ifs2.close();
}

/*
测试数据:
10
f 小明 10000 900
F 张三 3000 800
f 李四 4000 700
f 王五 5000 600
F 赵六 6000 500
T AAA 10000 900
t BBB 3000 800
T CCC 4000 700
t DDD 5000 600
t EEE 6000 500
11
12
4
王五
7
3
小明
小二
7
8
5
赵六
7
2
BBB
7
6
赵六
6
BBB
7
9
8
2
DD
2
DDD
7
9
10
11
12
0
*/

/**
 * 备注:
 * 1.这个程序的静态的统计人数不好写, 主要是因为可恢复删除那里, 删除时未调用析构函数, 导致统计出错
 *   我暂时先: 遍历pWorker数组, 运用dynamic_cast动态类型转换来求出具体人数
 *
 * 2.那个静态的统计分数和平均分的函数呢?
 *   该怎么写呀???
 *
 * 3.复制构造函数有什么用处呢?
 *
 * 4.这个程序我本来想直接将数据存到文件中, 进行修改, 删除, 但是这样好复杂啊 (⊙﹏⊙)
 *   所以我把程序写成保存文件的形式, 这样简单些
 * 
 * 5.C++怎样修改文件的某一行数据?
 * 
 * 6.强制转换: static_cast和dynamic_cast是什么意思?
 * 
 */

运行截图

C++练手小项目:职工工资信息管理系统_#include