【C++实战】多态版商品库存管理系统:从设计到实现,吃透面向对象核心

在C++开发中,面向对象的三大特性(封装、继承、多态)是进阶的核心,而多态更是体现"开闭原则"、提升代码扩展性的关键。本文将以"多态版商品库存管理系统"为例,从需求拆解、类结构设计到代码实现、数据持久化,完整讲解如何用C++打造一个高扩展性的实战项目,附带完整可运行源码。

注:本文使用AI写作

一、项目背景与需求拆解

1.1 业务需求

开发一个通用的商品库存管理系统,支持不同类型商品(电子产品、服装、食品)的统一管理,核心需求包括:

  • 支持电子产品、服装、食品三类商品的增删改查;
  • 不同商品的库存价值计算逻辑不同(如服装含仓储费、食品临期打折);
  • 按商品类型统计库存数量和总价值;
  • 数据持久化(二进制文件存储,比文本文件更高效、安全);
  • 控制台交互,操作简单直观。

1.2 技术需求

  • 抽象基类+纯虚函数实现多态,体现开闭原则;
  • 封装库存管理逻辑,降低模块耦合;
  • 实现对象的二进制序列化/反序列化;
  • 合理使用STL容器(vector、map)提升开发效率。

二、核心设计思路

2.1 类结构设计(面向对象核心)

整个系统分为两层:商品层 (业务实体)和管理层(库存操作),类结构如下:
<<abstract>>
Product
-string id
-string name
-double price
-int quantity
+Product()
+~Product()
+virtual double calculateStockValue() : const = 0
+virtual void showInfo() : const = 0
+virtual string getType() : const = 0
+virtual void serialize(ofstream&) : const
+virtual void deserialize(ifstream&)
Electronics
-int warrantyPeriod
-string brand
+Electronics()
+double calculateStockValue() : const
+void showInfo() : const
+string getType() : const
+void serialize(ofstream&) : const
+void deserialize(ifstream&)
Clothing
-string size
-string color
-string material
+Clothing()
+double calculateStockValue() : const
+void showInfo() : const
+string getType() : const
+void serialize(ofstream&) : const
+void deserialize(ifstream&)
Food
-string productionDate
-string expirationDate
+Food()
+double calculateStockValue() : const
+void showInfo() : const
+string getType() : const
+void serialize(ofstream&) : const
+void deserialize(ifstream&)
InventoryManager
-vector products
-string filename
+~InventoryManager()
+addProduct(Product*)
+deleteProduct(string)
+showAllProducts()
+statByType()
+saveToFile()
+loadFromFile()

2.2 核心设计原则

  1. 抽象基类(Product) :定义纯虚函数calculateStockValue()showInfo()getType(),强制子类实现差异化逻辑,体现"抽象"特性;
  2. 多态实现:子类(Electronics/Clothing/Food)重写基类虚函数,通过基类指针统一管理不同类型商品;
  3. 封装:InventoryManager封装库存的增删改查、持久化逻辑,对外提供简洁接口;
  4. 开闭原则:新增商品类型(如日用品)只需继承Product类,无需修改原有库存管理代码。

三、核心功能实现

3.1 抽象基类Product实现

抽象基类是多态的核心,定义所有商品的通用属性和纯虚函数,同时提供二进制序列化/反序列化的基础实现:

cpp 复制代码
class Product {
protected:
    std::string id;         // 商品编号
    std::string name;       // 商品名称
    double price;           // 单价
    int quantity;           // 库存数量
public:
    Product(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0)
        : id(id), name(name), price(price), quantity(quantity) {}

    // 虚析构函数:多态基类必须有,保证子类析构正常
    virtual ~Product() = default;

    // 纯虚函数:强制子类实现差异化逻辑
    virtual double calculateStockValue() const = 0;
    virtual void showInfo() const = 0;
    virtual std::string getType() const = 0;

    // 通用接口:获取/设置属性
    std::string getId() const { return id; }
    int getQuantity() const { return quantity; }
    double getPrice() const { return price; }

    // 二进制序列化(基础属性)
    virtual void serialize(std::ofstream& ofs) const {
        size_t id_len = id.size();
        ofs.write(reinterpret_cast<const char*>(&id_len), sizeof(id_len));
        ofs.write(id.c_str(), id_len);
        // 其他属性序列化逻辑...
    }

    // 二进制反序列化(基础属性)
    virtual void deserialize(std::ifstream& ifs) {
        size_t id_len;
        ifs.read(reinterpret_cast<char*>(&id_len), sizeof(id_len));
        id.resize(id_len);
        ifs.read(&id[0], id_len);
        // 其他属性反序列化逻辑...
    }
};

3.2 子类实现(多态核心)

以服装类(Clothing)为例,重写基类纯虚函数,实现差异化的库存价值计算和信息展示:

cpp 复制代码
class Clothing : public Product {
private:
    std::string size;    // 尺码
    std::string color;   // 颜色
    std::string material;// 材质
public:
    Clothing(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0,
             std::string size = "", std::string color = "", std::string material = "")
        : Product(id, name, price, quantity), size(size), color(color), material(material) {}

    // 重写:服装库存价值含5%仓储费
    double calculateStockValue() const override {
        return price * quantity * 1.05;
    }

    // 重写:展示服装特有信息
    void showInfo() const override {
        std::cout << "【服装】" << std::endl;
        std::cout << "编号:" << id << " 名称:" << name << std::endl;
        std::cout << "单价:¥" << std::fixed << std::setprecision(2) << price 
                  << " 库存:" << quantity << " 尺码:" << size << " 颜色:" << color 
                  << " 材质:" << material << std::endl;
        std::cout << "库存总价值(含5%仓储费):¥" << calculateStockValue() << std::endl;
    }

    // 重写:返回商品类型
    std::string getType() const override {
        return "Clothing";
    }

    // 重写序列化:增加子类特有属性
    void serialize(std::ofstream& ofs) const override {
        Product::serialize(ofs); // 先序列化基类属性
        size_t size_len = size.size();
        ofs.write(reinterpret_cast<const char*>(&size_len), sizeof(size_len));
        ofs.write(size.c_str(), size_len);
        // 其他子类属性序列化...
    }
};

3.3 库存管理类(核心业务逻辑)

InventoryManager类封装所有库存操作,核心功能包括:

  • 商品增删改查:通过vector<Product*>存储商品指针,利用多态统一管理;
  • 按类型统计:用map统计不同类型商品的数量和价值;
  • 二进制持久化:序列化/反序列化所有商品数据到文件。
关键功能:按类型统计库存
cpp 复制代码
void statByType() {
    std::map<std::string, double> typeTotalValue; // 类型->总价值
    std::map<std::string, int> typeTotalQuantity; // 类型->总数量

    for (const auto& p : products) {
        std::string type = p->getType();
        typeTotalValue[type] += p->calculateStockValue();
        typeTotalQuantity[type] += p->getQuantity();
    }

    std::cout << "\n===== 按类型统计库存 =====" << std::endl;
    for (const auto& pair : typeTotalValue) {
        std::cout << "类型:" << pair.first 
                  << " 总数量:" << typeTotalQuantity[pair.first]
                  << " 总价值:¥" << std::fixed << std::setprecision(2) << pair.second << std::endl;
    }
}
关键功能:二进制文件持久化
cpp 复制代码
bool saveToFile() {
    std::ofstream ofs("inventory.dat", std::ios::binary | std::ios::trunc);
    if (!ofs.is_open()) {
        std::cout << "错误:无法打开文件!" << std::endl;
        return false;
    }

    // 先写入商品数量
    size_t count = products.size();
    ofs.write(reinterpret_cast<const char*>(&count), sizeof(count));

    // 写入每个商品(先写类型,再写对象)
    for (const auto& p : products) {
        std::string type = p->getType();
        size_t type_len = type.size();
        ofs.write(reinterpret_cast<const char*>(&type_len), sizeof(type_len));
        ofs.write(type.c_str(), type_len);
        p->serialize(ofs); // 多态序列化
    }

    ofs.close();
    return true;
}

3.4 控制台交互

提供简洁的菜单交互,支持用户添加不同类型商品、删除、查看、统计等操作:

cpp 复制代码
void showMenu() {
    std::cout << "\n===== 商品库存管理系统 =====" << 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 << "8. 退出系统" << std::endl;
    std::cout << "请输入操作编号:";
}

四、运行与测试

4.1 编译运行

bash 复制代码
# 编译(C++11及以上)
g++ -std=c++11 inventory_system.cpp -o inventory_system
# 运行
./inventory_system

4.2 测试流程

  1. 启动系统,自动加载数据(首次启动无数据);
  2. 选择"1"添加电子产品:输入编号、名称、品牌、单价、库存、保修期;
  3. 选择"2"添加服装:输入编号、名称、尺码、颜色、材质、单价、库存;
  4. 选择"5"查看所有商品,验证多态展示效果;
  5. 选择"6"按类型统计,验证库存价值计算逻辑;
  6. 选择"7"保存数据,生成inventory.dat二进制文件;
  7. 退出系统后重新启动,验证数据加载功能。

五、项目扩展与优化

5.1 功能扩展

  1. 新增商品类型:只需继承Product类,重写纯虚函数,无需修改InventoryManager;
  2. 库存预警:添加库存数量阈值,低于阈值时提示补货;
  3. 日期解析:优化食品类,解析生产日期/保质期,动态判断是否临期;
  4. 异常处理:自定义异常类(如重复编号、非法价格),提升鲁棒性。

5.2 性能优化

  1. 内存管理:使用智能指针(unique_ptr/shared_ptr)替代裸指针,避免内存泄漏;
  2. 批量操作:支持批量导入/导出商品数据;
  3. 异步保存:多线程异步写入文件,提升交互响应速度。

六、核心知识点总结

  1. 多态的核心应用:通过抽象基类+纯虚函数实现不同商品的差异化逻辑,体现开闭原则;
  2. 二进制持久化:相比文本文件,二进制序列化更高效、安全,适合复杂对象存储;
  3. STL容器的灵活使用:vector存储多态对象、map实现按类型统计,提升开发效率;
  4. 面向对象设计:封装、继承、多态的综合应用,打造高扩展性的模块化系统。

完整源码

cpp 复制代码
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <iomanip>
#include <ctime>
#include <algorithm>

// 抽象基类:商品
class Product {
protected:
    std::string id;         // 商品编号
    std::string name;       // 商品名称
    double price;           // 单价
    int quantity;           // 库存数量
public:
    // 构造函数
    Product(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0)
        : id(id), name(name), price(price), quantity(quantity) {}

    // 虚析构函数(多态基类必须有)
    virtual ~Product() = default;

    // 纯虚函数:计算库存总价值(强制子类实现)
    virtual double calculateStockValue() const = 0;

    // 纯虚函数:展示商品信息(强制子类实现)
    virtual void showInfo() const = 0;

    // 纯虚函数:获取商品类型(用于分类统计)
    virtual std::string getType() const = 0;

    // 获取商品编号(用于查找/删除)
    std::string getId() const { return id; }

    // 获取库存数量
    int getQuantity() const { return quantity; }

    // 设置库存数量
    void setQuantity(int q) { quantity = q; }

    // 获取单价
    double getPrice() const { return price; }

    // 二进制序列化(写入文件)
    virtual void serialize(std::ofstream& ofs) const {
        // 写入基础属性(注意:string需要先写长度,再写内容)
        size_t id_len = id.size();
        ofs.write(reinterpret_cast<const char*>(&id_len), sizeof(id_len));
        ofs.write(id.c_str(), id_len);

        size_t name_len = name.size();
        ofs.write(reinterpret_cast<const char*>(&name_len), sizeof(name_len));
        ofs.write(name.c_str(), name_len);

        ofs.write(reinterpret_cast<const char*>(&price), sizeof(price));
        ofs.write(reinterpret_cast<const char*>(&quantity), sizeof(quantity));
    }

    // 二进制反序列化(读取文件)
    virtual void deserialize(std::ifstream& ifs) {
        // 读取基础属性
        size_t id_len;
        ifs.read(reinterpret_cast<char*>(&id_len), sizeof(id_len));
        id.resize(id_len);
        ifs.read(&id[0], id_len);

        size_t name_len;
        ifs.read(reinterpret_cast<char*>(&name_len), sizeof(name_len));
        name.resize(name_len);
        ifs.read(&name[0], name_len);

        ifs.read(reinterpret_cast<char*>(&price), sizeof(price));
        ifs.read(reinterpret_cast<char*>(&quantity), sizeof(quantity));
    }
};

// 电子产品子类
class Electronics : public Product {
private:
    int warrantyPeriod; // 保修期(月)
    std::string brand;  // 品牌
public:
    Electronics(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0,
                int warranty = 0, std::string brand = "")
        : Product(id, name, price, quantity), warrantyPeriod(warranty), brand(brand) {}

    // 重写:计算库存价值(电子产品无额外费用,直接单价*数量)
    double calculateStockValue() const override {
        return price * quantity;
    }

    // 重写:展示信息
    void showInfo() const override {
        std::cout << "【电子产品】" << std::endl;
        std::cout << "编号:" << id << " 名称:" << name << " 品牌:" << brand << std::endl;
        std::cout << "单价:¥" << std::fixed << std::setprecision(2) << price 
                  << " 库存:" << quantity << " 保修期:" << warrantyPeriod << "个月" << std::endl;
        std::cout << "库存总价值:¥" << calculateStockValue() << std::endl;
        std::cout << "-------------------------" << std::endl;
    }

    // 重写:获取类型
    std::string getType() const override {
        return "Electronics";
    }

    // 重写序列化(增加子类特有属性)
    void serialize(std::ofstream& ofs) const override {
        Product::serialize(ofs); // 先序列化基类属性
        ofs.write(reinterpret_cast<const char*>(&warrantyPeriod), sizeof(warrantyPeriod));
        
        size_t brand_len = brand.size();
        ofs.write(reinterpret_cast<const char*>(&brand_len), sizeof(brand_len));
        ofs.write(brand.c_str(), brand_len);
    }

    // 重写反序列化
    void deserialize(std::ifstream& ifs) override {
        Product::deserialize(ifs); // 先反序列化基类属性
        ifs.read(reinterpret_cast<char*>(&warrantyPeriod), sizeof(warrantyPeriod));
        
        size_t brand_len;
        ifs.read(reinterpret_cast<char*>(&brand_len), sizeof(brand_len));
        brand.resize(brand_len);
        ifs.read(&brand[0], brand_len);
    }
};

// 服装子类
class Clothing : public Product {
private:
    std::string size;    // 尺码
    std::string color;   // 颜色
    std::string material;// 材质
public:
    Clothing(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0,
             std::string size = "", std::string color = "", std::string material = "")
        : Product(id, name, price, quantity), size(size), color(color), material(material) {}

    // 重写:计算库存价值(服装需加5%的仓储费)
    double calculateStockValue() const override {
        return price * quantity * 1.05; // 含5%仓储费
    }

    // 重写:展示信息
    void showInfo() const override {
        std::cout << "【服装】" << std::endl;
        std::cout << "编号:" << id << " 名称:" << name << std::endl;
        std::cout << "单价:¥" << std::fixed << std::setprecision(2) << price 
                  << " 库存:" << quantity << " 尺码:" << size << " 颜色:" << color 
                  << " 材质:" << material << std::endl;
        std::cout << "库存总价值(含5%仓储费):¥" << calculateStockValue() << std::endl;
        std::cout << "-------------------------" << std::endl;
    }

    // 重写:获取类型
    std::string getType() const override {
        return "Clothing";
    }

    // 重写序列化
    void serialize(std::ofstream& ofs) const override {
        Product::serialize(ofs);
        
        size_t size_len = size.size();
        ofs.write(reinterpret_cast<const char*>(&size_len), sizeof(size_len));
        ofs.write(size.c_str(), size_len);

        size_t color_len = color.size();
        ofs.write(reinterpret_cast<const char*>(&color_len), sizeof(color_len));
        ofs.write(color.c_str(), color_len);

        size_t material_len = material.size();
        ofs.write(reinterpret_cast<const char*>(&material_len), sizeof(material_len));
        ofs.write(material.c_str(), material_len);
    }

    // 重写反序列化
    void deserialize(std::ifstream& ifs) override {
        Product::deserialize(ifs);
        
        size_t size_len;
        ifs.read(reinterpret_cast<char*>(&size_len), sizeof(size_len));
        size.resize(size_len);
        ifs.read(&size[0], size_len);

        size_t color_len;
        ifs.read(reinterpret_cast<char*>(&color_len), sizeof(color_len));
        color.resize(color_len);
        ifs.read(&color[0], color_len);

        size_t material_len;
        ifs.read(reinterpret_cast<char*>(&material_len), sizeof(material_len));
        material.resize(material_len);
        ifs.read(&material[0], material_len);
    }
};

// 食品子类
class Food : public Product {
private:
    std::string productionDate; // 生产日期
    std::string expirationDate; // 保质期
public:
    Food(std::string id = "", std::string name = "", double price = 0.0, int quantity = 0,
         std::string prodDate = "", std::string expDate = "")
        : Product(id, name, price, quantity), productionDate(prodDate), expirationDate(expDate) {}

    // 重写:计算库存价值(临期食品打8折)
    double calculateStockValue() const override {
        // 简单模拟:如果保质期小于7天,打8折
        // 实际项目中可解析日期计算,这里简化处理
        return price * quantity * 0.8;
    }

    // 重写:展示信息
    void showInfo() const override {
        std::cout << "【食品】" << std::endl;
        std::cout << "编号:" << id << " 名称:" << name << std::endl;
        std::cout << "单价:¥" << std::fixed << std::setprecision(2) << price 
                  << " 库存:" << quantity << std::endl;
        std::cout << "生产日期:" << productionDate << " 保质期至:" << expirationDate << std::endl;
        std::cout << "库存总价值(临期8折):¥" << calculateStockValue() << std::endl;
        std::cout << "-------------------------" << std::endl;
    }

    // 重写:获取类型
    std::string getType() const override {
        return "Food";
    }

    // 重写序列化
    void serialize(std::ofstream& ofs) const override {
        Product::serialize(ofs);
        
        size_t prod_len = productionDate.size();
        ofs.write(reinterpret_cast<const char*>(&prod_len), sizeof(prod_len));
        ofs.write(productionDate.c_str(), prod_len);

        size_t exp_len = expirationDate.size();
        ofs.write(reinterpret_cast<const char*>(&exp_len), sizeof(exp_len));
        ofs.write(expirationDate.c_str(), exp_len);
    }

    // 重写反序列化
    void deserialize(std::ifstream& ifs) override {
        Product::deserialize(ifs);
        
        size_t prod_len;
        ifs.read(reinterpret_cast<char*>(&prod_len), sizeof(prod_len));
        productionDate.resize(prod_len);
        ifs.read(&productionDate[0], prod_len);

        size_t exp_len;
        ifs.read(reinterpret_cast<char*>(&exp_len), sizeof(exp_len));
        expirationDate.resize(exp_len);
        ifs.read(&expirationDate[0], exp_len);
    }
};

// 库存管理类
class InventoryManager {
private:
    std::vector<Product*> products; // 存储所有商品指针(多态)
    const std::string filename = "inventory.dat"; // 二进制文件名称

    // 辅助函数:根据编号查找商品索引
    int findProductIndex(const std::string& id) {
        for (int i = 0; i < products.size(); ++i) {
            if (products[i]->getId() == id) {
                return i;
            }
        }
        return -1; // 未找到
    }

public:
    // 析构函数:释放所有商品指针
    ~InventoryManager() {
        for (auto& p : products) {
            delete p;
        }
        products.clear();
    }

    // 添加商品
    void addProduct(Product* p) {
        if (findProductIndex(p->getId()) != -1) {
            std::cout << "错误:商品编号 " << p->getId() << " 已存在!" << std::endl;
            delete p; // 避免内存泄漏
            return;
        }
        products.push_back(p);
        std::cout << "商品添加成功!" << std::endl;
    }

    // 删除商品
    bool deleteProduct(const std::string& id) {
        int index = findProductIndex(id);
        if (index == -1) {
            std::cout << "错误:未找到编号为 " << id << " 的商品!" << std::endl;
            return false;
        }
        delete products[index]; // 释放内存
        products.erase(products.begin() + index);
        std::cout << "商品删除成功!" << std::endl;
        return true;
    }

    // 展示所有商品
    void showAllProducts() {
        if (products.empty()) {
            std::cout << "库存为空!" << std::endl;
            return;
        }
        for (const auto& p : products) {
            p->showInfo(); // 多态调用
        }
    }

    // 按类型统计库存
    void statByType() {
        std::map<std::string, double> typeTotalValue; // 类型 -> 总价值
        std::map<std::string, int> typeTotalQuantity; // 类型 -> 总数量

        for (const auto& p : products) {
            std::string type = p->getType();
            typeTotalValue[type] += p->calculateStockValue();
            typeTotalQuantity[type] += p->getQuantity();
        }

        std::cout << "\n===== 按类型统计库存 =====" << std::endl;
        for (const auto& pair : typeTotalValue) {
            std::cout << "类型:" << pair.first 
                      << " 总数量:" << typeTotalQuantity[pair.first]
                      << " 总价值:¥" << std::fixed << std::setprecision(2) << pair.second << std::endl;
        }

        // 计算所有商品总价值
        double total = 0.0;
        for (const auto& pair : typeTotalValue) {
            total += pair.second;
        }
        std::cout << "所有商品库存总价值:¥" << std::fixed << std::setprecision(2) << total << std::endl;
    }

    // 保存数据到二进制文件
    bool saveToFile() {
        std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
        if (!ofs.is_open()) {
            std::cout << "错误:无法打开文件 " << filename << " 进行写入!" << std::endl;
            return false;
        }

        // 先写入商品数量
        size_t count = products.size();
        ofs.write(reinterpret_cast<const char*>(&count), sizeof(count));

        // 写入每个商品(先写类型,再写对象)
        for (const auto& p : products) {
            std::string type = p->getType();
            size_t type_len = type.size();
            ofs.write(reinterpret_cast<const char*>(&type_len), sizeof(type_len));
            ofs.write(type.c_str(), type_len);
            p->serialize(ofs); // 多态序列化
        }

        ofs.close();
        std::cout << "数据已保存到 " << filename << "!" << std::endl;
        return true;
    }

    // 从二进制文件加载数据
    bool loadFromFile() {
        // 先释放原有数据
        for (auto& p : products) {
            delete p;
        }
        products.clear();

        std::ifstream ifs(filename, std::ios::binary);
        if (!ifs.is_open()) {
            std::cout << "提示:未找到数据文件 " << filename << ",将创建新库存!" << std::endl;
            return false;
        }

        // 读取商品数量
        size_t count;
        ifs.read(reinterpret_cast<char*>(&count), sizeof(count));

        // 读取每个商品
        for (size_t i = 0; i < count; ++i) {
            // 读取商品类型
            size_t type_len;
            ifs.read(reinterpret_cast<char*>(&type_len), sizeof(type_len));
            std::string type(type_len, '\0');
            ifs.read(&type[0], type_len);

            // 根据类型创建对应对象(多态)
            Product* p = nullptr;
            if (type == "Electronics") {
                p = new Electronics();
            } else if (type == "Clothing") {
                p = new Clothing();
            } else if (type == "Food") {
                p = new Food();
            }

            if (p) {
                p->deserialize(ifs); // 多态反序列化
                products.push_back(p);
            }
        }

        ifs.close();
        std::cout << "成功从 " << filename << " 加载 " << products.size() << " 个商品!" << std::endl;
        return true;
    }
};

// 控制台菜单
void showMenu() {
    std::cout << "\n===== 商品库存管理系统 =====" << 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 << "8. 退出系统" << std::endl;
    std::cout << "请输入操作编号:";
}

// 主函数
int main() {
    InventoryManager manager;
    // 启动时加载数据
    manager.loadFromFile();

    int choice;
    while (true) {
        showMenu();
        std::cin >> choice;
        std::cin.ignore(); // 忽略换行符

        switch (choice) {
            case 1: { // 添加电子产品
                std::string id, name, brand;
                double price;
                int quantity, warranty;

                std::cout << "请输入电子产品信息:" << std::endl;
                std::cout << "编号:"; getline(std::cin, id);
                std::cout << "名称:"; getline(std::cin, name);
                std::cout << "品牌:"; getline(std::cin, brand);
                std::cout << "单价:"; std::cin >> price;
                std::cout << "库存数量:"; std::cin >> quantity;
                std::cout << "保修期(月):"; std::cin >> warranty;

                manager.addProduct(new Electronics(id, name, price, quantity, warranty, brand));
                break;
            }
            case 2: { // 添加服装
                std::string id, name, size, color, material;
                double price;
                int quantity;

                std::cout << "请输入服装信息:" << std::endl;
                std::cout << "编号:"; getline(std::cin, id);
                std::cout << "名称:"; getline(std::cin, name);
                std::cout << "尺码:"; getline(std::cin, size);
                std::cout << "颜色:"; getline(std::cin, color);
                std::cout << "材质:"; getline(std::cin, material);
                std::cout << "单价:"; std::cin >> price;
                std::cout << "库存数量:"; std::cin >> quantity;

                manager.addProduct(new Clothing(id, name, price, quantity, size, color, material));
                break;
            }
            case 3: { // 添加食品
                std::string id, name, prodDate, expDate;
                double price;
                int quantity;

                std::cout << "请输入食品信息:" << std::endl;
                std::cout << "编号:"; getline(std::cin, id);
                std::cout << "名称:"; getline(std::cin, name);
                std::cout << "生产日期(格式:YYYY-MM-DD):"; getline(std::cin, prodDate);
                std::cout << "保质期至(格式:YYYY-MM-DD):"; getline(std::cin, expDate);
                std::cout << "单价:"; std::cin >> price;
                std::cout << "库存数量:"; std::cin >> quantity;

                manager.addProduct(new Food(id, name, price, quantity, prodDate, expDate));
                break;
            }
            case 4: { // 删除商品
                std::string id;
                std::cout << "请输入要删除的商品编号:";
                getline(std::cin, id);
                manager.deleteProduct(id);
                break;
            }
            case 5: { // 查看所有商品
                manager.showAllProducts();
                break;
            }
            case 6: { // 按类型统计
                manager.statByType();
                break;
            }
            case 7: { // 保存数据
                manager.saveToFile();
                break;
            }
            case 8: { // 退出
                manager.saveToFile(); // 退出前自动保存
                std::cout << "感谢使用,再见!" << std::endl;
                return 0;
            }
            default:
                std::cout << "输入错误,请输入1-8之间的数字!" << std::endl;
                break;
        }
    }

    return 0;
}

写在最后

本项目是C++面向对象编程的经典实战案例,覆盖了抽象类、多态、STL、文件IO等核心知识点,既适合新手巩固基础,也适合进阶开发者理解"开闭原则"的实际应用。通过这个项目,你不仅能掌握代码实现,更能理解面向对象设计的核心思想------让代码更易扩展、更易维护

如果觉得本文有帮助,欢迎点赞、收藏、关注,后续会持续分享更多C++实战项目。

相关推荐
运维行者_2 小时前
2026 技术升级,OpManager 新增 AI 网络拓扑与带宽预测功能
运维·网络·数据库·人工智能·安全·web安全·自动化
Elastic 中国社区官方博客2 小时前
Elasticsearch:上下文工程 vs. 提示词工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
忧郁的橙子.2 小时前
26期_01_Pyhton文件的操作
开发语言·python
余瑜鱼鱼鱼2 小时前
线程和进程的区别和联系
java·开发语言·jvm
小唐同学爱学习2 小时前
如何解决海量数据存储
java·数据库·spring boot·mysql
清酒难咽2 小时前
算法案例之分治法
c++·经验分享·算法
小屁猪qAq2 小时前
强符号和弱符号及应用场景
c++·弱符号·链接·编译
头发还没掉光光2 小时前
HTTP协议从基础到实战全解析
linux·服务器·网络·c++·网络协议·http
wWYy.2 小时前
详解redis(15):缓存雪崩
数据库·redis·缓存