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

目录

一、管理系统的需求

二、创建项目 

三、创建管理类

3.1 创建文件

3.2 知识扩展

3.2.1 头文件和源文件各司其职 

3.2.2 头文件中第一行的#pragma once语句

1. 为什么需要头文件保护?

2. #pragma once 的作用

3. #pragma once vs. 传统的 #ifndef 方式

四、菜单功能

4.1 添加成员函数

4.2 菜单功能实现

 4.3 测试菜单功能

 五、退出功能(0.退出管理程序的设计)

5.1 提供功能接口

5.2 实现退出功能

5.3 测试退出功能

六、 创建职工类

6.1 创建职工抽象类

6.2 创建普通员工类

6.3 创建经理类

6.4 创建老板类 

6.5 测试多态 

七、添加职工

7.1 功能分析

7.2 功能实现

7.3 测试添加 

八、文件交互--写文件

8.1 设置文件路径

8.2 成员函数声明

8.3 保存文件功能实现

8.4 功能测试

九、文件交互-读文件

9.1 文件未创建

9.2 文件存在但数据为空

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

9.3.1 获取记录的职工人数

9.3.2 初始化数组

十、显示职工

10.1 显示职工函数声明 

10.2 显示职工函数实现

10.3 测试显示职工功能

十一、删除职工

11.1 删除职工函数声明

11.2 职工是否存在函数声明

11.3 职工是否存在函数实现

11.4 删除职工函数实现

11.5 测试删除职工函数功能

十二、 修改职工

12.1 修改职工函数声明

12.2 修改职工函数实现

12.3 修改职工函数功能演示

十三、查找职工

13.1 查找职工函数声明

13.2 查找职工函数具体实现

13.3 测试查找职工函数功能

十四、排序

14.1 排序函数声明

14.2 排序函数具体实现

14.3 测试排序函数功能

十五、清空文件

15.1 清空函数声明

15.2 清空文件函数实现

15.3 清空功能测试

十六、完整代码


作者使用的Visual Studio版本为VS2019,操作系统为WindowsX64

一、管理系统的需求

职工管理系统可以用来管理公司内所有员工的信息
本教程主要利用C++来实现一个基于多态的职工管理系统

公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责
普通员工职责:完成经理交给的任务
经理职责:完成老板交给的任务,并下发任务给员工
老板职责:管理公司所有事务


管理系统中需要实现的功能如下:

  1. 退出管理程序:退出当前管理系统
  2. 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
  3. 显示职工信息:显示公司内部所有职工的信息
  4. 删除离职职工:按照编号删除指定的职工
  5. 修改职工信息:按照编号修改职工个人信息
  6. 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
  7. 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
  8. 清空所有文档:清空文件中记录的所有职工信息(清空前需要再次确认,防止误删)

二、创建项目 

打开Visual Studio 2019,点击创建新项目,创建新的C++项目,如下所示: 

 按照如下步骤创建空的C++项目,如下:

 然后确定项目名称、路径,最后点击创建,如下所示:

按照如下步骤添加文件:
然后根据如下步骤添加源文件:


点击添加按钮之后,得到如下所示的界面:

至此,项目已创建完毕,在项目文件夹中你可以找到如下所示的文件:

三、创建管理类

管理类负责的内容如下:

  1. 菜单功能:与用户的沟通菜单界面
  2. 对职工增删改查的操作
  3. 与文件的读写交互

3.1 创建文件

        在头文件和源文件的文件夹下分别创建 workerManager.h 和 workerManager.cpp 文件,如下所示:

        workerManager.h 中的内容如下,主要是类的声明,没有具体的实现,具体的实现会在workerManager.cpp文件中。

#pragma once // 防止头文件重复包含
#include<iostream>

class workerManager {
public:
	// 构造函数
	workerManager();

	// 析构函数
	~workerManager();
};

 workerManager.cpp文件中的内容如下:

#include "workerManager.h"

workerManager::workerManager(){
	// 具体实现
}

workerManager::~workerManager() {
	// 具体实现
}

至此,职工管理类创建完毕。 

3.2 知识扩展

3.2.1 头文件和源文件各司其职 

在 C++ 代码组织中,.h 头文件和 .cpp 源文件各有明确的职责:

.h 头文件(声明)

头文件的主要作用是声明类、函数、常量等接口,让其他文件可以引用它,而不包含具体的实现。

通常放在 .h 文件中的内容:

  1. 头文件保护(防止重复包含)
  2. 类的声明
  3. 成员变量和成员函数的声明
  4. 常量、宏定义
  5. 类型定义(typedefusingenum
  6. 结构体、模板
  7. 头文件的引用(#include

示例:workerManager.h

#ifndef WORKERMANAGER_H
#define WORKERMANAGER_H

#include <iostream>
#include <vector>
using namespace std;

class WorkerManager {
public:
    WorkerManager();  // 构造函数
    ~WorkerManager(); // 析构函数

    void addWorker();  // 添加员工
    void showWorkers(); // 显示所有员工
private:
    vector<string> workerList; // 员工列表
};

#endif // WORKERMANAGER_H

.cpp 源文件(实现)

源文件主要实现 .h 头文件中声明的内容,用于存放代码逻辑。

通常放在 .cpp 文件中的内容:

  1. 包含对应的 .h 头文件
  2. 类的具体实现
  3. 函数的具体实现
  4. 局部变量、辅助函数
  5. 业务逻辑

示例:workerManager.cpp

#include "workerManager.h"

WorkerManager::WorkerManager() {
    cout << "WorkerManager 构造函数调用!" << endl;
}

WorkerManager::~WorkerManager() {
    cout << "WorkerManager 析构函数调用!" << endl;
}

void WorkerManager::addWorker() {
    string name;
    cout << "请输入员工姓名:";
    cin >> name;
    workerList.push_back(name);
}

void WorkerManager::showWorkers() {
    cout << "员工列表:" << endl;
    for (const auto& worker : workerList) {
        cout << worker << endl;
    }
}

总结

文件类型 主要内容 示例
.h 头文件 类的声明,函数原型,宏定义,类型定义 class WorkerManager { ... };
.cpp 源文件 类的实现,成员函数的定义,逻辑代码 void WorkerManager::addWorker() { ... }

这样分离的好处是:

  1. 提高代码复用性(多个 .cpp 文件可以共享同一个 .h
  2. 编译加速(修改 .cpp 不会导致所有代码重新编译)
  3. 增强可读性(头文件只关注接口,.cpp 处理具体实现)

3.2.2 头文件中第一行的#pragma once语句

.h文件中第一行一般是#pragma once,这是什么?

#pragma once 是一个头文件保护机制,用于防止头文件被多次包含,导致编译错误。


1. 为什么需要头文件保护?

在 C++ 中,如果一个头文件被多个 .cpp 文件包含,或者间接被自身包含,就可能导致重复定义错误

示例(没有头文件保护,可能导致重复定义):

// workerManager.h
#include <iostream>
class WorkerManager {
public:
    void show();
};
// main.cpp
#include "workerManager.h"
#include "workerManager.h"  // 头文件被重复包含

错误:重复定义 WorkerManager


2. #pragma once 的作用

#pragma once 让编译器在同一个编译单元中只包含一次头文件,即使多次 #include 也不会重复编译。

推荐写法:

// workerManager.h
#pragma once
#include <iostream>

class WorkerManager {
public:
    void show();
};

3. #pragma once vs. 传统的 #ifndef 方式

在早期 C++ 代码中,头文件保护通常使用 #ifndef 宏:

#ifndef WORKERMANAGER_H
#define WORKERMANAGER_H

#include <iostream>

class WorkerManager {
public:
    void show();
};

#endif // WORKERMANAGER_H

这种方式的原理:

  1. #ifndef WORKERMANAGER_H:如果宏 WORKERMANAGER_H 未定义,则继续执行代码。
  2. #define WORKERMANAGER_H:定义 WORKERMANAGER_H,确保下一次包含时被跳过。
  3. #endif:结束 #ifndef 保护范围。

两者的比较:

方式 优点 缺点
#pragma once 代码简洁,避免命名冲突,编译器优化 可能不被非常旧的编译器支持(但现代编译器都支持)
#ifndef 宏保护 适用于所有编译器 代码冗长,容易因宏命名冲突导致错误

现代 C++ 开发中,一般推荐 #pragma once,除非需要兼容极老的编译器。

四、菜单功能

功能描述:与用户的沟通界面

4.1 添加成员函数

在管理类 workerManager.h中添加成员函数 void Show_Menu();

4.2 菜单功能实现

在管理类 workerManager.cpp 中实现成员函数 void Show_Menu(); 

void workerManager::Show_Menu() {
	// 具体实现
	std::cout << "**********************************************" << std::endl;
	std::cout << "************* 欢迎使用职工管理系统 ***********" << std::endl;
	std::cout << "*************** 0.退出管理程序 ***************" << std::endl;
	std::cout << "*************** 1.增加职工信息 ***************" << std::endl;
	std::cout << "*************** 2.显示职工信息 ***************" << std::endl;
	std::cout << "*************** 3.删除离职职工 ***************" << std::endl;
	std::cout << "*************** 4.修改职工信息 ***************" << std::endl;
	std::cout << "*************** 5.查找职工信息 ***************" << std::endl;
	std::cout << "*************** 6.按照编号排序 ***************" << std::endl;
	std::cout << "*************** 7.清空所有文档 ***************" << std::endl;
	std::cout << "**********************************************" << std::endl;
	std::cout << std::endl;

}

 4.3 测试菜单功能

职工管理系统.cpp 文件中测试菜单功能:

#include<iostream>
#include"workerManager.h"

int main() {
	workerManager wm; // 实例化管理类对象
	wm.Show_Menu(); // 调用菜单功能函数
	return 0;
}

运行效果图: 

 五、退出功能(0.退出管理程序的设计)

5.1 提供功能接口

在main函数中提供分支选择,提供每个功能接口:

#include<iostream>
#include"workerManager.h"

int main() {
	workerManager wm; // 实例化管理类对象
	

	int choice = 0; // 定义用户选择的选项
	while (true) {
		wm.Show_Menu(); // 调用菜单功能函数
		std::cout << "请输入您的选择:" << std::endl;
		std::cin >> choice;
		switch (choice) {
		case 0: // 退出系统
			break;
		case 1: // 添加职工
			break;
		case 2: // 显示职工
			break;
		case 3: // 删除职工
			break;
		case 4: // 修改职工
			break;
		case 5: // 查找职工
			break;
		case 6: // 排序职工
			break;
		case 7: // 清空文件
			break;
		default:
			system("cls");
			break;
		}
	}
	return 0;
}

5.2 实现退出功能

在workerManager.h 中提供退出系统的成员函数 void exitSystem();

// workerManager.h
#pragma once // 防止头文件重复包含
#include<iostream>

class workerManager {
public:
	// 构造函数
	workerManager();

	// 展示菜单
	void Show_Menu();
	
	// 退出系统
	void exitSystem();

	// 析构函数
	~workerManager();
};

 在workerManager.cpp 中提供具体的功能实现:

// workerManager.cpp
// 退出系统的具体实现
void workerManager::exitSystem(){
	std::cout << "欢迎下次使用:" << std::endl;
	system("pause");
	exit(0);
}

5.3 测试退出功能

在main函数(main函数位于 职工管理系统.cpp 文件)switch-case 语句分支0选项中,调用退出程序的接口:

 运行测试效果如图:

六、 创建职工类

6.1 创建职工抽象类

职工的分类为:普通员工、经理、老板
将三种职工抽象到一个类(worker)中,利用多态管理不同职工种类
职工的属性为:职工编号、职工姓名、职工所在部门编号
职工的行为为:岗位职责信息描述,获取岗位名称
头文件文件夹下创建文件worker.h文件并且添加如下代码:

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

// 职工抽象基类
class Worker {
public:
	// 显示职工个人信息
	virtual void showinfo() = 0; 
	// 获取岗位名称
	virtual std::string getDeptName() = 0;
private:
	int m_Id; // 职工编号
	std::string m_Name; // 职工姓名
	int m_DeptId; // 职工所在部门名称编号
};

6.2 创建普通员工类

普通员工类继承职工抽象基类,并重写父类中的纯虚函数
在头文件和源文件的文件夹下分别创建 employee.h 和employee.cpp文件

employee.h 中代码如下: 

// employee.h
#pragma once
#include"worker.h"
#include<iostream>

// 创建普通员工类
class Employee:public Worker {
public:
	// 构造函数
	Employee(int id, std::string name, int dId);
	// id:员工编号
	// name:员工姓名
	// dId:员工部门编号

	// 显示个人信息
	void showinfo()override;

	// 获取职工岗位名称
	std::string getDeptName()override;
};

employee.cpp 中代码如下: 

// employee.cpp
#include"employee.h"
#include<iostream>

// 构造函数
Employee::Employee(int id, std::string name, int dId) {
	this->m_Id = id;
	this->m_Name = name;
	this->m_DeptId = dId;
}

// 显示个人信息
void Employee::showinfo(){
	std::cout << "职工编号:" << this->m_Id
		<< "\t职工姓名:" << this->m_Name
		<< "\t岗位:" << this->getDeptName()
		<< "\t岗位职责:完成经理交给的任务" << std::endl;
}

// 获取职工岗位名称
std::string Employee::getDeptName() {
	return std::string("员工");
}

6.3 创建经理类

经理类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似
在头文件和源文件的文件夹下分别创建manager.h和manager.cpp文件
manager.h中代码如下:

// manager.h
#pragma once
#include"worker.h"
#include<iostream>

// 创建经理类
class Manager :public Worker {
public:
	// 构造函数
	Manager(int id, std::string name, int dId)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值