C++类对象无法存储整数并跨函数正确输出问题求助
问题分析与解决
核心问题
你遇到的是局部对象作用域与生命周期问题:
lich_swamp()中创建的Inv inv是该函数的局部对象,它的coins值仅属于这个对象;menu()里重新创建了一个全新的Inv inv局部对象,这个对象的coins是类默认初始化的0,和之前lich_swamp()里的对象无任何关联,所以显示0是正常的(异常长负数可能是未正确初始化的情况,但你的类已默认给coins赋值0,所以大概率显示0)。
解决方法
下面给出几种适合新手的实现方案,按推荐程度排序:
方案1:传递对象引用(推荐,符合面向对象设计)
让menu()函数接收Inv对象的引用,这样它操作的是外部传入的真实背包对象,而非新建的空对象。
- 修改
menu()函数定义:
// 参数为Inv&,表示引用传递 void menu(Inv& inv) { std::cout << "0:{return to game}\n"; std::cout << "1:{view inventory}\n"; std::cout << "2:{view achievements}\n"; std::cout << "3:{player info}\n"; int menu_choice; std::cin >> menu_choice; switch (menu_choice) { case 0: system("CLS"); break; case 1: system("CLS"); inv.print_inv(); return; case 2: system("CLS"); //num_twopr(ach); return; case 3: system("CLS"); plyr_print(); return; } }
- 修改
Inv::print_inv()中调用menu()的代码,传递当前对象的引用:
void Inv::print_inv() { int inv_choice; std::cout << "x" << coins << " Coin(s) in your inventory."; std::cout << "\n0: [RETURN TO MENU]\n"; std::cin >> inv_choice; switch (inv_choice) { case 0: system("CLS"); menu(*this); // *this代表当前Inv对象本身,传递引用给menu break; } }
- 在
lich_swamp()中调用menu()时,传入当前的inv对象:
void lich_swamp() { Inv inv; do { std::cout << "---Irrelevant---"; std::cout << "[Insert Number]\n"; inv.c_add(); if (inv.coins <= 4) { system("CLS"); inv.c_print(); // 这里添加调用menu的逻辑,比如玩家选择返回菜单时 menu(inv); break; } else if (inv.coins > 4) { system("CLS"); std::cout << "---Irrelevant---"; dth_e1(); console_death(); return; } } while (inv.coins < 1); }
方案2:使用全局对象(新手易上手,但不推荐大型项目)
把Inv对象定义在所有函数外部,变成全局变量,这样所有函数都能访问同一个对象:
// 在main.cpp最顶部、所有函数之前定义 Inv player_inv; void lich_swamp() { do { std::cout << "---Irrelevant---"; std::cout << "[Insert Number]\n"; player_inv.c_add(); // 使用全局对象 if (player_inv.coins <= 4) { system("CLS"); player_inv.c_print(); break; } else if (player_inv.coins > 4) { system("CLS"); std::cout << "---Irrelevant---"; dth_e1(); console_death(); return; } } while (player_inv.coins < 1); } void menu() { std::cout << "0:{return to game}\n"; std::cout << "1:{view inventory}\n"; std::cout << "2:{view achievements}\n"; std::cout << "3:{player info}\n"; int menu_choice; std::cin >> menu_choice; switch (menu_choice) { case 0: system("CLS"); break; case 1: system("CLS"); player_inv.print_inv(); // 使用全局对象 return; case 2: system("CLS"); //num_twopr(ach); return; case 3: system("CLS"); plyr_print(); return; } }
方案3:单例模式(适合全局唯一的背包)
如果游戏中玩家只有一个背包,可以把Inv设计成单例类,确保整个程序只有一个实例:
// 修改Inv类的头文件 #ifndef INV_UTILS #define INV_UTILS #include "C:/Otherincludedfile.h" #include <iostream> class Inv { private: int longsword = 0; int coins = 0; // 私有构造函数,禁止外部创建对象 Inv() {} public: // 获取唯一实例的静态方法 static Inv& getInstance() { static Inv instance; return instance; } // 禁止拷贝和赋值 Inv(const Inv&) = delete; void operator=(const Inv&) = delete; void c_add(); void c_print(); void print_inv(); // 提供访问coins的方法(封装成员变量,符合面向对象规范) int getCoins() const { return coins; } void setCoins(int val) { coins = val; } }; #endif // 修改c_add函数 void Inv::c_add() { std::cin >> coins; } // 使用时,所有地方都通过Inv::getInstance()获取同一个对象 void lich_swamp() { Inv& inv = Inv::getInstance(); do { std::cout << "---Irrelevant---"; std::cout << "[Insert Number]\n"; inv.c_add(); if (inv.getCoins() <= 4) { system("CLS"); inv.c_print(); break; } else if (inv.getCoins() > 4) { system("CLS"); std::cout << "---Irrelevant---"; dth_e1(); console_death(); return; } } while (inv.getCoins() < 1); } void menu() { std::cout << "0:{return to game}\n"; std::cout << "1:{view inventory}\n"; std::cout << "2:{view achievements}\n"; std::cout << "3:{player info}\n"; int menu_choice; Inv& inv = Inv::getInstance(); std::cin >> menu_choice; switch (menu_choice) { case 0: system("CLS"); break; case 1: system("CLS"); inv.print_inv(); return; case 2: system("CLS"); //num_twopr(ach); return; case 3: system("CLS"); plyr_print(); return; } }
关键知识点补充
- 局部对象:在函数内部定义的对象,生命周期从定义处开始,到函数结束时销毁,每个函数的局部对象都是独立的。
- 引用传递:函数参数用
Type&时,传递的是对象本身的引用,操作的是原对象而非副本。 - 封装:方案3把
coins设为私有,通过get/set方法访问,是面向对象的良好实践,避免直接修改成员变量。
内容的提问来源于stack exchange,提问作者SevenSixFive
相关产品推荐
相关产品推荐

