product应仅管理不可变属性,库存由独立的inventoryitem类负责,二者通过id关联;库存操作须通过事务性接口,避免直接修改字段。

商品类 Product 应该只管自身属性,别掺和库存逻辑
很多初学者一上来就让 Product 自己存 stock_count、提供 decreaseStock() 方法,结果导致商品复用困难——比如同一款手机在不同仓库、不同渠道的库存要分开管理,硬塞进一个类里后续根本没法扩展。
正确做法是把商品看作「不可变描述」:ID、名称、单价、分类这些不随业务变动的元数据归它管;而库存是独立的、带状态的实体。两者通过 ID 关联,而非继承或嵌套。
-
Product的构造函数建议用const std::string&接名称,避免拷贝;ID 类型推荐int或std::string(若需支持编码如 "P2024-001") - 所有字段设为
private,只提供get方法,不暴露set—— 商品信息修改应走专门的更新流程,不是随意改属性 - 别在
Product里重载operator 或实现比较逻辑,留到容器或算法层统一处理
库存类 InventoryItem 必须绑定具体商品和位置
库存不是抽象数字,它永远属于某个商品、在某个地点(仓库/门店/货架)。所以 InventoryItem 至少得有两个关键成员:product_id(关联 Product)和 location_id(比如 "WH-A" 表示A仓)。
如果直接存 Product 对象,会引发深拷贝或生命周期问题;更合理的是只存 ID,并在需要时从全局 ProductCatalog 查找。这样既解耦,又支持热更新商品信息。
-
quantity类型建议用int(非负),配合addQuantity(int delta)方法做带校验的增减,禁止直接赋值 - 加个
last_updated时间戳(std::chrono::system_clock::time_point),排查库存不一致时很有用 - 不要给
InventoryItem加operator==,它的相等性取决于(product_id, location_id)组合,而不是所有字段
用 std::map 或 std::unordered_map 管理商品与库存的映射关系
常见错误是用 vector<product></product> 存所有商品,再遍历找匹配的库存——O(n) 查找在商品数过百后就明显卡顿。实际中商品查库存、库存反查商品都是高频操作,必须用键值结构。
推荐组合:std::unordered_map<int product></int> 存商品主表,std::unordered_map<:pair std::string>, InventoryItem></:pair> 存库存(key 是 (product_id, location_id))。注意 C++20 前 std::pair 不能直接作 unordered_map key,得自己写哈希特化,不如改用字符串拼接 key,例如 std::to_string(pid) + "@" + loc。
- 如果库存查询常按商品 ID 聚合(比如查某商品全渠道总库存),额外维护一个
std::unordered_map<int std::vector>></int>索引,避免每次遍历 - 避免用
std::map替代std::unordered_map——除非你真需要按键有序遍历,否则红黑树开销不必要 - 所有 map 的 insert 操作建议用
try_emplace而非insert或[],防止意外构造临时对象
库存变动必须走事务性接口,不能裸露 quantity 成员
看到有人直接写 item.quantity -= 2;,这是危险信号。库存变更涉及校验(是否够卖)、日志、通知,甚至可能触发补货逻辑。裸改字段会让这些逻辑散落在各处,后期维护成本爆炸。
应该提供明确语义的接口,比如 InventoryManager::reserve(int product_id, const std::string& location, int amount),内部完成:检查可用库存 → 扣减 → 记录流水 → 返回成功/失败码。调用方只关心“我要锁2台iPhone”,不关心怎么锁。
- 返回值别用布尔,用枚举如
enum class ReserveResult { SUCCESS, INSUFFICIENT_STOCK, INVALID_LOCATION }; - 扣减前先对
InventoryItem加读锁(或用std::atomic_int如果只是单线程+简单场景),并发环境下裸改quantity必然出错 - 别在接口里抛异常处理业务错误(如缺货),异常该留给真正异常的情况(如数据库连接失败)
Product,什么时候该动 InventoryItem,以及谁来协调它们之间的联动。这个边界一旦模糊,三个月后你就得重写一半代码。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











