收银机程序中cashRegister对象如何访问inventory对象的数据?
收银机程序中CashRegister访问Inventory数据的优雅实现方案
问题描述
我正在开发大学课程的收银机程序,inventory类与cashRegister类分别在独立头文件中定义。在main函数中初始化了inventory对象inv并填充了itemList数据,但创建cashRegister对象register1后,调用printInventory时无法获取inv的itemList数据。试过按引用传递inv对象,虽能实现但感觉繁琐,想了解如何优雅实现cashRegister访问inv的itemList等数据。
现有代码结构如下:
Inventory.h
class inventory { protected: vector <item> itemList; fstream infile; public: void printList(); void fillInventory(); void fileOpen(); }; class item { protected: double price; string name; int amount; friend class inventory; };
Register.h
class cashRegister : protected inventory { private: vector <int> userChoice; double total = 0; public: void input(); void printReceipt(); void calcTotal(); const double getTotal(); }; void cashRegister::input() { int temp; try { do { cout << "\nPlease select an item using the corresponding item number.\n=> "; cin >> temp; if (cin.fail()) { throw(256); } else { if (temp == -1) { break; } else if (temp >= 0 && temp <= 10) { if (inventory.stockChecker(temp) == 1) { userChoice.push_back(temp); } } else { throw(1); } } cout << "\n\n"; printInventory(); } while (true); } catch (int error) { cout << "Input error: " << error << endl; cout << "Please enter a value from 0 to 10 to select an item (-1 to exit).\n"; cout << "----------------------------------------------------------------\n"; cin.clear(); cin.ignore(256, '\n'); input(); } }
main.cpp
#include"Inventory.h" #include"Register.h" int main() { inventory inv; inv.fileOpen(); inv.fillInventory(); inv.printInventory(); cashRegister register1; register1.input(); register1.calcTotal(); register1.printReceipt(); }
解决方案
方案1:使用组合而非继承(推荐)
当前的protected继承逻辑错误——收银机不是一种库存,两者是依赖关系:收银机需要调用库存的数据来完成工作。用组合(让cashRegister持有inventory的引用)才是符合面向对象设计的正确做法,代码更清晰且易于维护。
修改Register.h
// 先前向声明inventory类,避免头文件循环依赖 class inventory; class cashRegister { private: vector <int> userChoice; double total = 0; // 持有库存的引用,确保和外部库存实例生命周期一致 inventory& inv_ref; public: // 构造函数必须初始化引用成员 cashRegister(inventory& inv) : inv_ref(inv) {} void input(); void printReceipt(); void calcTotal(); const double getTotal(); }; // 修改input方法,通过引用访问库存数据 void cashRegister::input() { int temp; try { do { cout << "\n请输入对应商品编号选择商品(-1退出)\n=> "; cin >> temp; if (cin.fail()) { throw(256); } else { if (temp == -1) { break; } else if (temp >= 0 && temp <= 10) { // 通过引用调用库存的库存检查方法 if (inv_ref.stockChecker(temp) == 1) { userChoice.push_back(temp); } } else { throw(1); } } cout << "\n\n"; // 调用库存的打印方法 inv_ref.printInventory(); } while (true); } catch (int error) { cout << "输入错误: " << error << endl; cout << "请输入0-10之间的商品编号(-1退出)\n"; cout << "--------------------------------------------------------\n"; cin.clear(); cin.ignore(256, '\n'); input(); } }
修改main.cpp
#include"Inventory.h" #include"Register.h" int main() { inventory inv; inv.fileOpen(); inv.fillInventory(); inv.printInventory(); // 创建收银机时传入已初始化的库存引用 cashRegister register1(inv); register1.input(); register1.calcTotal(); register1.printReceipt(); }
优势:
- 符合单一职责原则:库存类专注管理库存,收银类专注收银逻辑
- 避免继承带来的冗余成员暴露,代码耦合度更低
- 明确依赖关系,后续扩展或修改更方便
方案2:将Inventory设计为单例(适合全局唯一库存场景)
如果整个收银系统只会有一个库存实例,可以把inventory设计成单例类,让收银机直接获取全局的库存实例,无需手动传递引用。
修改Inventory.h
class inventory { protected: vector <item> itemList; fstream infile; // 私有构造函数,禁止外部直接创建实例 inventory() {} // 禁用拷贝构造和赋值运算符,确保单例唯一性 inventory(const inventory&) = delete; inventory& operator=(const inventory&) = delete; public: // 全局访问点,返回唯一的库存实例 static inventory& getInstance() { static inventory instance; return instance; } void printInventory(); void fillInventory(); void fileOpen(); bool stockChecker(int idx); // 假设你实现了这个库存检查方法 }; class item { protected: double price; string name; int amount; friend class inventory; };
修改Register.h中的input方法
void cashRegister::input() { // ... 其他代码不变 // 通过单例获取库存实例并调用方法 if (inventory::getInstance().stockChecker(temp) == 1) { userChoice.push_back(temp); } // ... inventory::getInstance().printInventory(); // ... }
修改main.cpp
#include"Inventory.h" #include"Register.h" int main() { // 获取全局库存实例 inventory& inv = inventory::getInstance(); inv.fileOpen(); inv.fillInventory(); inv.printInventory(); cashRegister register1; register1.input(); register1.calcTotal(); register1.printReceipt(); }
优势:无需传递引用,全局可访问;劣势:单例会增加测试难度(难以模拟不同的库存状态),仅适合库存全局唯一的场景。
方案3:修正原有继承设计(不推荐)
你原有的protected继承会让cashRegister拥有自己独立的itemList,和main中创建的inv完全是两个实例,所以无法共享数据。如果非要用继承,只能把inv的数据复制到register1中,但这完全不符合业务逻辑——库存应该是共享的,所以不推荐这种方式。
内容的提问来源于stack exchange,提问作者Yeonari
相关产品推荐
相关产品推荐

