博客作业:软件缺陷分析与二次开发实践(图书管理系统)

news/2025/2/26 19:39:58/文章来源:https://www.cnblogs.com/50light/p/18739457

(1)来源
本次分析的代码来源于网络上的一个C++书籍购买系统项目。该项目模拟了不同用户类型(如会员、贵宾、学生等)购买书籍时的折扣计算和购买记录保存功能。原始代码虽能运行,但存在一些设计缺陷和潜在问题。
(2)运行环境+运行结果截图
运行环境:

环境:Windows 11 + Visual Studio 2022

原始运行截图:

(3)主要问题列表与改进方案

问题 改进方案
输入验证不足 添加输入验证循环,处理非法输入(如非数字输入)。
折扣计算逻辑耦合 将折扣率提取为虚函数getDiscountRate(),支持灵活扩展。
缺乏购买历史记录 新增purchaseHistory字段,记录用户购买记录。
(4)新代码(关键改进部分)
  1. 在Buyer类中添加虚函数getDiscountRate和addPurchaseHistory
点击查看代码
class Buyer {
protected:vector<const Book*> purchaseHistory; 
public:virtual double getDiscountRate() const = 0; // 新增虚函数,返回折扣率(如0.8表示8折)void addPurchaseHistory(const Book* book) { purchaseHistory.push_back(book); }void displayPurchaseHistory() const {cout << "===== 购买历史 =====" << endl;for (const auto& book : purchaseHistory) {cout << "书籍: " << book->title << ", 价格: $" << book->price << endl;}}
};
2. 子类实现getDiscountRate
点击查看代码
// Layfolk(普通人)
double getDiscountRate() const override { return 1.0; } // 原价// Member(会员)
double getDiscountRate() const override {static const double discounts[5] = {0.95, 0.90, 0.85, 0.80, 0.70};return (leaguer_grade >=1 && leaguer_grade <=5) ? discounts[leaguer_grade-1] : 1.0;
}// StudentMember(学生会员)
double getDiscountRate() const override { return 0.85; } // 直接返回固定折扣// ... 其他子类类似实现
改进3:购买历史记录
点击查看代码
class Order {
private:vector<const book*> purchaseHistory; // 新增字段
public:void addBook(book* b) {purchaseHistory.push_back(b);totalAmount += b->getprice();}void displayHistory() const {cout << "===== 购买历史 =====" << endl;for (const auto& b : purchaseHistory) {cout << "图书: " << b->getbook_name() << ", 价格: " << b->getprice() << endl;}}
};
5.重构后的测试截图 ![](https://img2024.cnblogs.com/blog/3607082/202502/3607082-20250226192815040-1143786296.png) 输入验证测试 ![](https://img2024.cnblogs.com/blog/3607082/202502/3607082-20250226192906316-1188985295.png) 购买历史查看 ![](https://img2024.cnblogs.com/blog/3607082/202502/3607082-20250226192925069-2084314808.png) (6)总结 难点与耗时:

设计虚函数需确保所有子类正确实现getDiscountRate,避免遗漏导致编译错误。

调试购买历史记录的指针管理

逆向工程思考:

发现原代码未充分利用多态特性,通过虚函数统一接口可大幅提升扩展性。

数据持久化(如购买历史)应优先考虑存储必要信息而非对象指针,降低耦合。

收获:
通过本次二次开发,深入理解了C++资源管理、多态的应用场景,以及如何通过增量改进提升遗留代码质量。同时意识到单元测试在复杂系统中的必要性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/890262.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客添加看板娘

{% note info flat %} 本文转载自偷掉月亮的阿硕,本博客看板娘基于该教程搭建。 文章作者: 偷掉月亮的阿硕 文章链接: https://moonshuo.cn/posts/16544.html {% endnote %}

预祝2025省选嗨翻天

预祝2025省选嗨翻天\(T1\) A. 单峰序列 \(8pts\)部分分\(8pts\) :枚举每个数在单峰序列的左边还是右边,求次数做法同 luogu P3531 [POI 2012] LIT-Letters 。点击查看代码 int a[500010],b[500010],c[500010],ans[500010],id; vector<int>l,r; struct BIT {int c[50001…

配置github图床+picgo-core上传+jsdelivr

GitHub图床GitHub图床部分参考自教程Github图床+PicGo+JsDelivr+imgbot+automerge-action.imgbot图片压缩图片压缩部分参考自教程Github图床+PicGo+JsDelivr+imgbot+automerge-action.automerge-action最新版地址https://github.com/marketplace/actions/merge-pull-requests-a…

让博客在关键日子弹窗-变灰-放烟花

本文大体上参考自[1],新增了放烟花功能。前置教程 参见[1:1]。 {% note warning flat%}SweetAlert库应该在day.js和lunar.js前面引入!{% endnote %} 放烟花实现SweetAlert2库[2],支持弹窗含有图片,也就是可以弹窗一个放烟花的gif,当然你也可以使用html的visible属性来可视化…

2025中国十大HR SaaS厂商,企业应该如何选择最佳合作伙伴

人力资源软件供应商的价值已远超工具范畴——它们是组织能力的“放大器”、管理革命的“催化剂”。在数字化转型中,企业通过与其深度合作,不仅能实现运营效率的指数级提升,更将人力资本转化为战略资产,构建起适应AI时代的核心竞争力。选择与怎样的供应商同行,将直接决定企…

redis - [09] redis.conf详解

题记部分 配置文件unit单位对大小写不敏感。可以将多个配置文件配置进来绑定ip保护模式 & 端口守护进程,默认是no,需要改成yes如果需要后台运行,需要制定进程文件(pid)指定日志级别,生产环境默认notice。logfile: 日志文件位置名配置数据库的数量,默认16个是否总是…

试用一下Qexo这个Hexo博客内容管理系统

本文由Qexo书写并发布。Qexo介绍 Qexo | 一个美观、强大的在线 静态博客 管理器 (oplog.cn) 本文就不详细介绍Qexo了,官方文档写的很清晰了2333测试样式 测试一下github markdown样式是否正确显示。 This README can be used as a reference for github-flavored-markdown sty…

双链表与双循环链表的C语言实现

双链表与双循环链表的C语言实现 目录双链表与双循环链表的C语言实现双链表的增删查改双循环链表的增删查改 双链表的增删查改 /*双链表*/#include<stdio.h> #include<stdlib.h>typedef struct Node{int data;struct Node* pre;struct Node* next; }Node;Node* init…

Redis十大数据类型及命令详解

Redis数据类型 1、redis字符串(String)string是redis最基本的类型,一个key对应一个value string类型是二进制安全的,意思是redis的string可以包含任何数据。例如说是jpg图片或者序列化对象 一个redis中字符串value最多可以是512M应用场景: 缓存:存储用户会话、页面内容(…

第6章-控件

控件,继承自 System.Windows.Contorl 类 控件分类内容控件:Label/Button/ToolTip/ScrollViewer 带有标题的内容控件:TabItem/GroupBox/Expander 文本控件:Textbox/PasswordBox/RichTextBox 列表控件:ListBox/ComboBox 基于范围的控件:Slider/ProgressBar 日期控件:Calen…

第5章-路由事件

Handler: 处理器 Preview: 预览、这指隧道 Raise: 引发 Bubble: 冒泡 Handled: 已处理理解路由事件 事件路由允许源自某个元素的事件由另一个元素引发。 定义、注册和封装路由事件 public partial class Window1 : Window {// 定义路由事件,必须是 static readonly// 类型 Rou…