C++车辆管理系统[2026-01-05]
题目 4 “车辆管理系统设计”
1、问题描述
车辆管理系统主要负责各种车辆的常规信息管理工作。
系统中的车辆主要有大客车、小轿车和卡车。每种车辆有车辆编号、车牌号、车辆制造公司、车辆购买时间、车辆型号(大客车、小轿车和卡车)、总公里数、耗油量 / 公里、基本维护费用、养路费、累计总费用等信息。大客车还有载客量(最大载客数)信息,小轿车还有箱数(两厢或三厢)信息,卡车还有载重量等信息。
每台车辆当月总费用 = 油价 * 耗油量 / 公里 + 基本维护费用。
基本维护费用:客车:2000 元 / 月,小轿车:1000 元 / 月,卡车:1500 元 / 月
2、功能要求
(1)添加车辆:主要完成车辆信息的添加,要求编号唯一。当添加了重复的编号时,则提示数据添加重复并取消添加;当车辆信息库已满,则提示不能再添加新的数据。
(2)查询车辆:
可按照三种方式来查询物品,分别为:
按车辆制造公司查询:输入车辆制造公司,输出所查询的信息,若不存在该记录,则提示 “该车辆制造公司不存在!”;
按编号查询:输入编号,输出所查询的信息,若不存在该记录,则提示 “该编号不存在!”;
按类别查询:输入类别,输出所查询的信息,若不存在记录,则提示 “该类别没有车辆!”;
(3)显示车辆信息库:输出当前车辆信息库中所有车辆信息,每条记录占据一行。
(4)编辑功能:可根据查询结果对相应的记录进行修改,修改时注意编号的唯一性。
(5)删除车辆:主要完成车辆信息的删除。如果当前车辆信息库为空,则提示 “车辆信息库为空!”,并返回操作;否则,输入要删除的编号,根据编号删除该车辆的记录,如果该编号不在车辆信息库库中,则提示 “该编号不存在”。
(6)统计信息
输出当前车辆信息库中总物品数,以及按车辆类别,统计出当前车辆信息库中各类别的物品数并显示。
(7)车辆信息存盘:将当前程序中的车辆信息存入文件中。
(8)读出车辆信息:从文件中将车辆信息读入程序。
3、问题的解决方案
根据系统功能要求,可以将问题解决分为以下步骤:
(1)应用系统分析,建立该系统的功能模块框图以及界面的组织和设计;
(2)分析系统中的各个实体及它们之间的关系;
(3)根据问题描述,设计系统的类层次;
(4)完成类层次中各个类的描述;
(5)完成类中各个成员函数的定义;
(6)完成系统的应用模块;
(7)功能调试;
(8)完成系统总结报告。
源码联系UP主 -> https://space.bilibili.com/329101171
一、系统概述
本车辆管理系统基于C++语言实现,采用面向对象的设计思想,完成对大客车、小轿车、卡车三类车辆的信息管理。系统核心围绕车辆信息的增删改查、统计分析、文件持久化展开,通过抽象基类+派生类的多态设计封装不同车辆的共性与特性,利用vector容器存储车辆对象指针,实现灵活的内存管理与数据操作,最终将车辆信息持久化到cars.txt文件中。
二、代码结构分析
1. 核心类结构
| 类名 | 作用 | 关键设计 |
|---|---|---|
CarType(枚举) | 定义车辆类型(大客车/小轿车/卡车) | 为派生类类型标识提供统一枚举值 |
Car(抽象基类) | 封装所有车辆的通用属性与接口 | 纯虚函数定义edit/show/load/save等核心接口;保护成员封装通用属性(编号、车牌号等);提供通用的信息编辑/展示/文件读写方法 |
Bus/Sedan/Truck(派生类) | 实现不同车辆的特有属性与逻辑 | 继承Car并实现纯虚函数;扩展特有属性(载客量/箱数/载重);重写总费用计算逻辑 |
CarException(异常类) | 处理自定义业务异常 | 封装异常信息,用于编号重复等场景的错误提示 |
PayrollSystem(系统类) | 封装业务逻辑(增删改查/统计/文件操作) | 核心调度类,整合所有功能,管理Car对象容器 |
2. 核心数据结构
CarArray:typedef vector<Car*> CarArray,利用容器存储不同类型车辆的指针,依托多态特性统一管理大客车、小轿车、卡车对象。- 文件存储格式:
cars.txt中先存储车辆总数,再依次存储车辆类型、通用属性、特有属性,实现数据持久化。
3. 核心流程
系统入口为main函数,实例化PayrollSystem并调用run()方法启动循环菜单;用户选择功能后,由PayrollSystem调用对应方法(如addCar()/searchCar()),最终通过Car及其派生类的多态方法完成具体操作,操作后自动同步数据到文件。
三、功能实现与需求对比分析
需求功能清单与实现情况
| 功能要求 | 实现情况 | 不足/问题 |
|---|---|---|
| 1. 添加车辆(编号唯一、库满提示) | ✅ 实现编号唯一性校验(generateCarID()抛异常);✅ 车辆类型选择+信息录入;✅ 自动存盘 | ❌ 未实现“信息库已满”提示(vector无容量限制,无校验逻辑) |
| 2. 查询车辆(按制造公司/编号/类别) | ✅ 按编号查询(searchCarByID());✅ 按类别查询(searchCarByTypeName()) | ❌ 未实现“按制造公司查询”;❌ 提示语与要求不符(要求“该编号不存在!”,代码提示“未找到相关记录!”) |
| 3. 显示车辆信息库(所有记录分行输出) | ✅showCars()遍历输出所有车辆;✅showCarsLine()表格化排序输出 | 完全满足需求 |
| 4. 编辑车辆(修改记录、保证编号唯一) | ✅ 按编号查找后调用edit()修改信息;✅ 修改后自动存盘 | ✅ 编号作为唯一标识,修改时未开放编号编辑,天然保证唯一性 |
| 5. 删除车辆(空库提示、按编号删除) | ✅ 按编号删除并释放内存;✅ 删除后自动存盘 | ❌ 未检查“信息库为空”,无对应提示;❌ 提示语与要求不符 |
| 6. 统计信息(总数、按类别统计数量) | ✅ 统计总数;✅ 统计平均/最高/最低总费用 | ❌ 未实现“按车辆类别统计数量” |
| 7. 车辆信息存盘 | ✅save()方法将内存数据写入cars.txt | ✅ 包含车辆类型、通用属性、特有属性,存储完整 |
| 8. 读出车辆信息 | ✅load()方法从cars.txt读取数据到内存 | ❌ 存在冗余时间判断逻辑(time(NULL)范围判断),可能导致加载失败 |
核心逻辑细节
总费用计算:
需求定义“当月总费用 = 油价 × 耗油量/公里 + 基本维护费用”,代码中:- 大客车:
2000 + (8 * fuel_ / km_)(8为硬编码油价,2000为基本维护费) - 小轿车:
1000 + (8 * fuel_ / km_) - 卡车:
1500 + (8 * fuel_ / km_)
✅ 逻辑符合需求,但油价硬编码导致扩展性差。
- 大客车:
多态设计:
派生类通过重写edit/show/load/save等纯虚函数,实现“同一接口、不同行为”,例如Bus::edit()会先调用基类editCar()录入通用信息,再调用editBus()录入载客量,符合面向对象设计原则。
四、代码优点
- 面向对象设计规范:
抽象基类封装共性,派生类扩展特性,多态性保证代码复用性与可扩展性;属性私有化/保护化,通过成员函数访问,符合封装原则。 - 内存管理安全:
PayrollSystem析构函数调用free()释放所有Car对象指针,避免内存泄漏;容器vector动态管理对象,灵活适配数据量变化。 - 用户交互友好:
菜单式交互逻辑清晰,表格化输出(setw格式化)提升信息可读性;自定义异常类CarException处理业务错误,提示明确。 - 文件持久化完整:
load()/save()方法覆盖所有车辆属性的读写,保证数据在程序重启后不丢失。
五、代码不足与问题
1. 功能缺失
- 核心查询功能缺失:未实现“按车辆制造公司查询”;
- 统计功能不完整:未按车辆类别统计数量;
- 边界校验缺失:添加/删除时未处理“库满/库空”场景;
- 提示语不统一:与需求指定的提示文案不符。
2. 逻辑与健壮性问题
- 冗余代码:
load()中time(NULL)的范围判断无业务意义,可能导致正常数据加载失败; - 输入校验缺失:公里数、油耗、养路费等数值未校验负数,小轿车箱数未限制“2/3”,购买时间无格式校验;
- 文件操作脆弱:未处理文件打开失败(如权限不足、文件不存在)的场景,无错误提示;
- 硬编码问题:油价(8元)、基本维护费等常量直接写死,无法灵活配置。
3. 代码风格与维护性
- 注释错误:
Truck::getSalesVolume()注释为“获取销售额”(实际为载重),属于笔误; - 裸指针风险:使用
Car*裸指针管理对象,手动内存管理易出错; - 排序效率低:手动实现冒泡排序,未使用
std::sort,数据量大时效率差。
六、改进建议
1. 补全缺失功能
- 按制造公司查询:新增
findCarByBrand()/searchCarByBrand()方法,遍历cars_匹配brand_属性; - 类别数量统计:在
statisticCars()中遍历cars_,统计TYPE_BUS/TYPE_SEDAN/TYPE_TRUCK的数量并输出; - 库满/库空校验:
// 添加车辆时检查库满constintMAX_CARS=100;// 定义最大容量if(cars_.size()>=MAX_CARS){throwCarException("车辆信息库已满,无法添加!");}// 删除车辆时检查库空if(cars_.empty()){cout<<"车辆信息库为空!"<<endl;return;} - 统一提示语:将提示文案封装为常量(如
const string ID_NOT_FOUND = "该编号不存在!"),替换所有硬编码提示。
2. 修复逻辑与健壮性问题
- 删除冗余代码:移除
load()中无关的时间判断逻辑; - 输入合法性校验:
// 校验数值非负cout<<"总公里数:";while(!(cin>>km_)||km_<0){cin.clear();// 清除错误状态cin.ignore(numeric_limits<streamsize>::max(),'\n');// 清空缓冲区cout<<"输入无效,请输入非负数:";} - 文件操作增强:
voidload(){ifstream input;input.open(getFilename(),ios::in);if(!input.is_open()){cout<<"文件打开失败,无法加载数据!"<<endl;return;}// 原有加载逻辑...} - 常量抽象:定义全局常量管理油价、维护费:
constdoubleOIL_PRICE=8.0;// 油价constdoubleBUS_MAINTENANCE=2000.0;// 大客车维护费constdoubleSEDAN_MAINTENANCE=1000.0;// 小轿车维护费constdoubleTRUCK_MAINTENANCE=1500.0;// 卡车维护费
3. 代码优化
- 智能指针替换裸指针:使用
unique_ptr<Car>管理车辆对象,避免手动释放内存:typedefvector<unique_ptr<Car>>CarArray;// 创建车辆时unique_ptr<Car>createCar(inttype){switch(type){caseTYPE_BUS:returnmake_unique<Bus>();caseTYPE_SEDAN:returnmake_unique<Sedan>();caseTYPE_TRUCK:returnmake_unique<Truck>();default:returnnullptr;}} - 排序优化:使用
std::sort替换手动冒泡排序:voidsortBySalary(){sort(cars_.begin(),cars_.end(),[](Car*a,Car*b){returna->totalFee()>b->totalFee();// 降序排序});} - 修正注释错误:统一注释与实际逻辑(如
Truck::getSalesVolume()改为“获取载重”)。
七、总结
本代码基于面向对象思想实现了车辆管理系统的核心功能,具备完整的增删改查、文件持久化能力,多态设计与内存管理保证了代码的基础质量。但存在功能缺失、输入校验不足、代码冗余等问题,需补全核心功能、优化逻辑健壮性、统一交互提示,进一步提升代码的可维护性与用户体验。
整体而言,代码框架清晰,核心逻辑正确,通过针对性改进后可完全满足需求定义的所有功能,且能提升系统的稳定性与扩展性。