You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

收银机程序中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 06:10:36