在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 核心设计原则
- 抽象基类(Product) :定义纯虚函数
calculateStockValue()、showInfo()、getType(),强制子类实现差异化逻辑,体现"抽象"特性; - 多态实现:子类(Electronics/Clothing/Food)重写基类虚函数,通过基类指针统一管理不同类型商品;
- 封装:InventoryManager封装库存的增删改查、持久化逻辑,对外提供简洁接口;
- 开闭原则:新增商品类型(如日用品)只需继承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"添加服装:输入编号、名称、尺码、颜色、材质、单价、库存;
- 选择"5"查看所有商品,验证多态展示效果;
- 选择"6"按类型统计,验证库存价值计算逻辑;
- 选择"7"保存数据,生成inventory.dat二进制文件;
- 退出系统后重新启动,验证数据加载功能。
五、项目扩展与优化
5.1 功能扩展
- 新增商品类型:只需继承Product类,重写纯虚函数,无需修改InventoryManager;
- 库存预警:添加库存数量阈值,低于阈值时提示补货;
- 日期解析:优化食品类,解析生产日期/保质期,动态判断是否临期;
- 异常处理:自定义异常类(如重复编号、非法价格),提升鲁棒性。
5.2 性能优化
- 内存管理:使用智能指针(unique_ptr/shared_ptr)替代裸指针,避免内存泄漏;
- 批量操作:支持批量导入/导出商品数据;
- 异步保存:多线程异步写入文件,提升交互响应速度。
六、核心知识点总结
- 多态的核心应用:通过抽象基类+纯虚函数实现不同商品的差异化逻辑,体现开闭原则;
- 二进制持久化:相比文本文件,二进制序列化更高效、安全,适合复杂对象存储;
- STL容器的灵活使用:vector存储多态对象、map实现按类型统计,提升开发效率;
- 面向对象设计:封装、继承、多态的综合应用,打造高扩展性的模块化系统。
完整源码
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++实战项目。