C++调用拷贝对象成员函数报错:request for member in non-class type
C++文字格斗游戏角色选择对象拷贝错误修复
错误代码示例(模拟你的问题代码)
#include <iostream> #include <string> class Fighter { private: std::string name; int hp; int attack; public: Fighter(std::string n, int h, int a) : name(n), hp(h), attack(a) {} Fighter(const Fighter& other) : name(other.name), hp(other.hp), attack(other.attack) {} void showInfo() { std::cout << "角色:" << name << ",血量:" << hp << ",攻击力:" << attack << std::endl; } }; int main() { Fighter warrior("战士", 100, 20); Fighter mage("法师", 70, 35); Fighter archer("弓箭手", 80, 25); // 错误:被解析为函数声明而非对象定义 Fighter choosingFighter(); int choice; do { std::cout << "请选择你的角色:1-战士,2-法师,3-弓箭手" << std::endl; std::cin >> choice; // 错误:循环内重复定义对象,作用域仅限当前分支 if(choice == 1) { Fighter choosingFighter(warrior); } else if(choice == 2) { Fighter choosingFighter(mage); } else if(choice == 3) { Fighter choosingFighter(archer); } else { std::cout << "无效选择,请重新输入!" << std::endl; } // 错误:循环条件逻辑颠倒,选对角色后仍会继续循环 } while(choice >=1 && choice <=3); // 错误:choosingFighter是函数声明,无法调用成员方法 choosingFighter.showInfo(); return 0; }
错误原因分析
- 函数声明混淆对象定义:
Fighter choosingFighter();被编译器识别为「返回Fighter类型、无参数的函数声明」,而非创建Fighter对象的语句。 - 循环内重复定义对象:if分支里定义的
choosingFighter作用域仅在当前分支内,循环结束后外部的「函数声明版choosingFighter」依然存在,无法访问分支内的有效对象。 - 循环条件逻辑错误:原条件
while(choice >=1 && choice <=3)会让用户选对角色后继续循环,违背了「选对则退出」的需求。
修正后的代码
#include <iostream> #include <string> class Fighter { private: std::string name; int hp; int attack; public: // 带参构造函数 Fighter(std::string n, int h, int a) : name(n), hp(h), attack(a) {} // 拷贝构造函数 Fighter(const Fighter& other) : name(other.name), hp(other.hp), attack(other.attack) {} // 默认构造函数:用于先声明对象,后续赋值 Fighter() : name(""), hp(0), attack(0) {} void showInfo() { std::cout << "角色:" << name << ",血量:" << hp << ",攻击力:" << attack << std::endl; } }; int main() { Fighter warrior("战士", 100, 20); Fighter mage("法师", 70, 35); Fighter archer("弓箭手", 80, 25); // 正确声明对象:使用默认构造创建,后续通过拷贝赋值初始化 Fighter choosingFighter; int choice; do { std::cout << "请选择你的角色:1-战士,2-法师,3-弓箭手" << std::endl; std::cin >> choice; // 直接给外部声明的choosingFighter赋值,避免重复定义 if(choice == 1) { choosingFighter = warrior; } else if(choice == 2) { choosingFighter = mage; } else if(choice == 3) { choosingFighter = archer; } else { std::cout << "无效选择,请重新输入!" << std::endl; } // 修正循环条件:仅当选择无效时继续循环 } while(choice < 1 || choice > 3); // 此时choosingFighter是有效对象,可正常调用方法 choosingFighter.showInfo(); return 0; }
关键修正点说明
- 给Fighter类添加默认构造函数,支持先声明对象再赋值的操作。
- 将
choosingFighter的声明移到循环外,确保其作用域覆盖后续的showInfo()调用,同时避免重复定义。 - 修正do-while循环条件,改为「选择不在1-3范围内时继续循环」,符合业务逻辑。
- 使用拷贝赋值运算符(编译器自动生成)给
choosingFighter赋值,完成角色拷贝。
内容的提问来源于stack exchange,提问作者MrMorgotheron
相关产品推荐
相关产品推荐

