8、C++项目实战:职工信息管理系统(继承与多态)

说实话,很多初学者学完C++的继承和多态,总觉得是纸上谈兵。我当年也一样,背了一堆虚函数表、抽象类的概念,但真要写个能跑的系统,脑子就一片空白。

这个项目,就是让你把继承和多态真正用起来。咱们要做一个职工信息管理系统,管理不同岗位的员工——经理、技术人员、销售员。每个岗位的工资计算方式不一样,但系统得统一处理。你想想看,这不就是多态的经典场景吗?

项目需求分析

先理清楚我们要做什么。系统需要管理三类员工:

  • 经理:固定月薪,比如8000块
  • 技术人员:按工作小时计费,每小时200元
  • 销售员:底薪加提成,底薪4000,提成按销售额的5%算

系统功能包括:添加员工、删除员工、修改信息、查询员工、显示所有员工工资。嗯,这里要注意,所有员工都得有编号、姓名、岗位类型这些基本信息。

类结构设计

核心思路是:设计一个抽象基类 Employee,里面放公共属性和一个纯虚函数 calcSalary()。然后三个派生类各自实现自己的工资计算逻辑。

关键设计点:

  • 基类用纯虚函数强制子类实现工资计算
  • 用虚析构函数确保派生类资源正确释放
  • vector<Employee*> 存储多态对象

我个人习惯把基类的接口设计得尽量简洁。你看下面这个基类,就三个虚函数:一个算工资,一个显示信息,一个返回岗位类型。够用就行,别整太复杂。

// Employee.h
#pragma once
#include <string>
#include <iostream>

class Employee {
protected:
    int id;
    std::string name;
    std::string position;

public:
    Employee(int id, const std::string& name, const std::string& pos)
        : id(id), name(name), position(pos) {}

    virtual ~Employee() {}  // 虚析构,重要!

    virtual double calcSalary() const = 0;  // 纯虚函数
    virtual void showInfo() const {
        std::cout << "编号: " << id
                  << " 姓名: " << name
                  << " 岗位: " << position;
    }

    int getId() const { return id; }
    std::string getPosition() const { return position; }
};

避坑指南:我曾经在项目里忘了给基类写虚析构函数,结果删除派生类对象时只调了基类析构,派生类里动态分配的内存全泄漏了。那会儿排查了一下午,最后发现是少了个 virtual 关键字。所以记住:只要基类有虚函数,析构函数一定要加 virtual

派生类实现

三个派生类的实现其实很直接。我挑一个技术人员的类给你看看:

// Technician.h
#pragma once
#include "Employee.h"

class Technician : public Employee {
private:
    double workHours;
    static const double HOURLY_RATE;  // 每小时200元

public:
    Technician(int id, const std::string& name, double hours)
        : Employee(id, name, "技术人员"), workHours(hours) {}

    double calcSalary() const override {
        return workHours * HOURLY_RATE;
    }

    void showInfo() const override {
        Employee::showInfo();
        std::cout << " 工时: " << workHours
                  << " 时薪: " << HOURLY_RATE
                  << " 工资: " << calcSalary() << std::endl;
    }
};

const double Technician::HOURLY_RATE = 200.0;

经理和销售员的实现类似,只是工资计算逻辑不同:

  • Manager:直接返回固定月薪 8000.0
  • Salesman:返回 baseSalary + salesAmount * 0.05

多态的核心用法

系统管理所有员工时,我们用基类指针的容器来存储:

std::vector<Employee*> employees;

// 添加员工
employees.push_back(new Manager(1001, "张三"));
employees.push_back(new Technician(1002, "李四", 160.0));
employees.push_back(new Salesman(1003, "王五", 50000.0));

// 遍历计算工资——多态就在这里体现
for (const auto& emp : employees) {
    emp->showInfo();  // 调用的是实际对象的showInfo
    std::cout << "本月工资: " << emp->calcSalary() << "元" << std::endl;
}

// 记得释放内存
for (auto& emp : employees) {
    delete emp;
}
employees.clear();

你看,循环里调用 calcSalary() 时,根本不用管它到底是经理还是销售员。C++的虚函数机制会自动找到正确的函数来执行。这就是多态的魅力——写一次循环,处理所有类型。

系统核心逻辑流程图

下面这张图展示了整个系统的类关系和调用流程,我建议你仔细看看:

Employee (抽象基类) +calcSalary() = 0 Manager 工资 = 固定月薪8000 Technician 工资 = 工时 × 200 Salesman 工资 = 底薪 + 提成 vector<Employee*> employees 存储基类指针,指向不同派生类对象 emp->calcSalary() 虚函数动态绑定,自动调用正确版本 核心:多态让代码统一处理不同类型

完整系统功能实现

系统的主控逻辑其实就是一个菜单循环,根据用户选择执行不同操作。我给出核心的几个函数签名:

class EmployeeManager {
private:
    std::vector<Employee*> employees;
    int nextId;

public:
    EmployeeManager() : nextId(1001) {}
    ~EmployeeManager();

    void addEmployee();      // 添加员工
    void deleteEmployee();   // 删除员工
    void modifyEmployee();   // 修改员工信息
    void queryEmployee();    // 查询员工
    void showAllSalary();    // 显示所有员工工资
    void run();              // 主菜单循环
};

addEmployee() 里,根据用户选择的岗位类型,创建不同的派生类对象:

void EmployeeManager::addEmployee() {
    std::string name;
    int type;
    std::cout << "请输入姓名: ";
    std::cin >> name;
    std::cout << "选择岗位 (1-经理 2-技术 3-销售): ";
    std::cin >> type;

    switch(type) {
        case 1:
            employees.push_back(new Manager(nextId++, name));
            break;
        case 2: {
            double hours;
            std::cout << "请输入本月工时: ";
            std::cin >> hours;
            employees.push_back(new Technician(nextId++, name, hours));
            break;
        }
        case 3: {
            double sales;
            std::cout << "请输入本月销售额: ";
            std::cin >> sales;
            employees.push_back(new Salesman(nextId++, name, sales));
            break;
        }
    }
    std::cout << "添加成功!" << std::endl;
}

注意事项:

  • 删除员工时,记得先 delete 对象再 erase 指针,否则内存泄漏
  • 修改员工信息时,如果岗位变了,需要先删除旧对象再创建新对象
  • 析构函数里要遍历容器 delete 所有员工对象

项目总结与经验分享

这个项目做完,你基本就掌握了继承和多态在实际项目中的用法。我总结几个关键点:

  • 纯虚函数定义接口:基类只声明做什么,不关心怎么做。子类自己决定实现细节。
  • 基类指针统一管理:用 vector<Employee*> 存所有员工,遍历时自动多态。
  • 虚析构保证安全:这是C++里最容易踩的坑之一,我当年就吃过亏。
  • 扩展性极强:如果以后要加新岗位(比如实习生、外包人员),只需要新增一个派生类,重写 calcSalary() 就行,现有代码一行都不用改。

说白了,继承和多态就是让你写出「对扩展开放,对修改关闭」的代码。这个项目虽然小,但背后的设计思想,你在任何大型C++项目里都能看到它的影子。


公众号:蓝海资料掘金营,微信deep3321