(1)来源
本次分析的代码来源于网络上的一个C++书籍购买系统项目。该项目模拟了不同用户类型(如会员、贵宾、学生等)购买书籍时的折扣计算和购买记录保存功能。原始代码虽能运行,但存在一些设计缺陷和潜在问题。
(2)运行环境+运行结果截图
运行环境:
环境:Windows 11 + Visual Studio 2022
原始运行截图:
(3)主要问题列表与改进方案
问题 | 改进方案 |
---|---|
输入验证不足 | 添加输入验证循环,处理非法输入(如非数字输入)。 |
折扣计算逻辑耦合 | 将折扣率提取为虚函数getDiscountRate(),支持灵活扩展。 |
缺乏购买历史记录 | 新增purchaseHistory字段,记录用户购买记录。 |
(4)新代码(关键改进部分) |
- 在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;}}
};
点击查看代码
// 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; } // 直接返回固定折扣// ... 其他子类类似实现
点击查看代码
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;}}
};
设计虚函数需确保所有子类正确实现getDiscountRate,避免遗漏导致编译错误。
调试购买历史记录的指针管理
逆向工程思考:
发现原代码未充分利用多态特性,通过虚函数统一接口可大幅提升扩展性。
数据持久化(如购买历史)应优先考虑存储必要信息而非对象指针,降低耦合。
收获:
通过本次二次开发,深入理解了C++资源管理、多态的应用场景,以及如何通过增量改进提升遗留代码质量。同时意识到单元测试在复杂系统中的必要性。