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

C++ dispenserType类重复调用默认构造 自定义值被覆盖问题

问题根因

值与赋值不符的核心原因是变量作用域规则+多实例独立存储,和构造函数逻辑无关:

  • staffDispenser()内if/else分支中声明的dispenserType dt是块级局部变量,仅在当前分支的大括号范围内有效,离开代码块就会被系统销毁,无法被外部函数访问
  • main函数开头声明的dispenserType dt是完全独立的另一个类实例,声明时默认调用无参构造将所有参数初始化为50,staffDispenser()内创建的局部对象和该实例无任何关联,因此读取时只能拿到默认值
  • 原代码存在额外语法问题:name、juice、c变量未定义,main函数中的item、cost数组全程未写入有效值,直接输出会读取未初始化的内存垃圾值
修复方案

核心思路是仅创建一次类实例,跨函数传递实例引用,避免重复创建对象触发无参构造覆盖参数,完全符合不允许删除两个构造函数的作业要求:

  • 调整staffDispenser函数返回值类型,让其直接返回初始化完成的dispenserType对象,不在函数内部生成用完即销毁的局部对象
  • 其他需要操作售货机的函数(比如要求实现的customerDispenser),通过引用传参的方式接收已经初始化好的实例,不要在函数内部重新声明dispenserType变量创建新对象
  • 补全原代码缺失的变量定义,修正变量读写逻辑的错误
修复后可运行代码
#include <iostream>
#include <string>
using namespace std;

// 补全原代码缺失的商品名数组定义
const string name[4] = {"Coke", "Juice", "Water", "Snack"};

class dispenserType
{
private:
    int numberOfItems[4] = {0,0,0,0};
    int cost[4] = {0,0,0,0};
public:
    // 保留作业要求的两个构造函数,不做修改
    dispenserType()
    {
       for (int i = 0; i < 4; i++) {
        numberOfItems[i] = 50;
        cost[i] = 50;
       }
    }
    dispenserType(int item[], int c[])
    {
        for (int i = 0; i<4;i++){
            numberOfItems[i] = item[i];
            cost[i] = c[i];
        }
    }
    int getNoOfItems(int i)
    {
        return numberOfItems[i];
    }
    int getCost(int i)
    {
        return cost[i];
    }
    void makeSale(int i)
    {
        numberOfItems[i] -= 1;
    }
};

// 修改函数返回值为dispenserType,返回初始化完成的实例
dispenserType staffDispenser()
{
    char choice;
    int item[4];
    int cost[4];

    cout << endl << "Do you want to asign values manually for each items? (Y for yes, N for no): ";
    cin >> choice;
    if (choice == 'Y' || choice == 'y') {
        for (int i = 0; i < 4; i++) {
            cout << "Enter the number of " << name[i] << ": ";
            cin >> item[i];
            cout << "Enter the cost of " << name[i] << " (in cents): ";
            cin >> cost[i];
            
        }
        // 返回使用自定义参数构造的对象
        return dispenserType(item, cost);
    }
    else {
        cout << endl << "Each item is set to 50 in quantity and also cost 50 cents" << endl;
        // 返回使用默认参数构造的对象
        return dispenserType();
    }
}

// 顾客功能函数示例:通过引用接收已初始化的实例,不会触发构造函数重置值
void customerDispenser(dispenserType &dt)
{
    // 此处编写顾客购买、查询等逻辑,直接操作传入的实例即可
    cout << endl << "Current item stock and price:" << endl;
    for (int i =0; i<4; i++){
        cout << name[i] << ": stock=" << dt.getNoOfItems(i) << ", price=" << dt.getCost(i) << " cents" << endl;
    }
}

int main()
{
    // 仅创建一次实例,接收staffDispenser返回的初始化完成的对象
    dispenserType dt = staffDispenser();
    int stock[4];
    int price[4];

    // 读取商品参数
    for (int i = 0; i < 4; i++) {
        stock[i] = dt.getNoOfItems(i);
        price[i] = dt.getCost(i);
    }
    
    // 输出校验结果
    cout << endl << "Final stock value: ";
    for (int i =0; i<4; i++){
        cout << stock[i] << " ";
    }
    cout << endl;
    cout << "Final price value: ";
    for (int i =0; i<4; i++){
        cout << price[i] << " ";
    }

    // 调用顾客功能,传入已初始化的实例
    customerDispenser(dt);

    return 0;
}
编码注意事项
  • 不要在代码块(if/for/while包裹的大括号内部)声明需要跨块、跨函数使用的对象,局部变量离开作用域会被直接销毁,外部无法访问
  • 所有需要操作同一售货机数据的函数,统一通过引用传递的方式传入已经初始化好的实例,不要在函数内部重新声明dispenserType dt创建新实例,就不会触发无参构造重置参数
  • 如果后续需要在多个模块中共享同一个售货机实例,也可以将实例定义为全局变量,但引用传递的方式代码耦合度更低,更推荐使用

内容的提问来源于stack exchange,提问作者I Forgot My Name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:01:04