成员变量存为引用vs指针:C++类实现及代码适配求助
C++类实现问题:Weapon、HumanA/HumanB的指针/引用用法修正
题目要求
实现Weapon类,包含string类型的type属性、返回const引用的getType()方法以及setType()方法;创建HumanA和HumanB类,两者均包含武器、名称属性,以及attack()函数,输出格式为:"NAME attacks with his WEAPON_TYPE"。需让给定的main()代码先后输出"crude spiked club"和"some other type of club"。
给定的main()代码如下:
int main(){ { Weapon club = Weapon("crude spiked club"); HumanA bob("Bob", club); bob.attack(); club.setType("some other type of club"); bob.attack(); } { Weapon club = Weapon("crude spiked club"); HumanB jim("Jim"); jim.setWeapon(club); jim.attack(); club.setType("some other type of club"); jim.attack(); } }
我的问题
- 希望不修改给定的
main()代码完成实现; - 当前
HumanB类存在指针相关错误,无法正确输出武器类型; - 明确何时适合将
Weapon存为指针/引用,原因是什么,是否符合题目要求。
当前代码
main.cpp
int main(){ { Weapon club = Weapon("crude spiked club"); HumanA bob("Bob", club); bob.attack(); club.setType("some other type of club"); bob.attack(); } { std::cout << "--------------------new section!!!-----------------------123" << "\n"; Weapon club = Weapon("big, crude spiked club"); HumanB jim("Jim"); jim.setWeapon(club); std::cout << "Weapon set" << "\n"; jim.attack(); club.setType("some other type of club"); jim.attack(); } return 0; }
Weapon.h
class Weapon { std::string type; public: const std::string& getType(); void setType(std::string t); Weapon(); Weapon(std::string t); };
Weapon.cpp
Weapon::Weapon() { type = "knucks"; } Weapon::Weapon(std::string t) { type = t; } const std::string& Weapon::getType() { const std::string& type = this->type; return type; } void Weapon::setType(std::string t) { this->type = t; }
HumanA.h
class HumanA { std::string name; Weapon* weapon; public: void attack(); HumanA() = default; HumanA(std::string n, Weapon& w); };
HumanA.cpp
HumanA::HumanA(std::string n, Weapon& w) { name = n; weapon = &w; } void HumanA::attack() { std::cout << name << " attacks with his " << weapon->getType() << "\n"; }
HumanB.h
class HumanB { std::string name; Weapon* weapon; public: void attack(); void setWeapon(Weapon w); HumanB(); HumanB(std::string name); };
HumanB.cpp
HumanB::HumanB(std::string n) { name = n; } void HumanB::setWeapon(Weapon w) { weapon = &w; std::cout << "SETTING WEAPON!: " << weapon << "\n"; //无法输出指针指向的地址值 } void HumanB::attack() { std::cout << name << " attacks with his " << weapon << "\n"; //无法输出指针指向的地址值 }
解决方案与解释
1. 不修改原main代码的正确实现
修正Weapon类
getType()方法需要声明为const成员函数,否则无法在const对象或const引用上调用;同时简化返回逻辑:
// Weapon.h const std::string& getType() const; // Weapon.cpp const std::string& Weapon::getType() const { return type; // 直接返回成员变量的const引用,无需额外定义局部变量 }
修正HumanA类
HumanA构造时必须绑定武器,且武器不会更换,使用引用更符合语义(避免空指针风险),同时用初始化列表优化构造:
// HumanA.h class HumanA { std::string name; const Weapon& weapon; // 用const引用,兼容const Weapon对象 public: void attack() const; HumanA(std::string n, const Weapon& w); HumanA() = delete; // 禁止默认构造,必须传入名称和武器 }; // HumanA.cpp HumanA::HumanA(std::string n, const Weapon& w) : name(std::move(n)), weapon(w) // 初始化列表构造 {} void HumanA::attack() const { std::cout << name << " attacks with his " << weapon.getType() << "\n"; }
修正HumanB类
HumanB可以先创建再设置武器,使用指针(支持null状态),同时setWeapon必须传引用避免临时对象导致野指针:
// HumanB.h class HumanB { std::string name; const Weapon* weapon = nullptr; // 初始化指针为nullptr public: void attack() const; void setWeapon(const Weapon& w); HumanB(std::string name); HumanB() = delete; // 禁止默认构造,必须传入名称 }; // HumanB.cpp HumanB::HumanB(std::string n) : name(std::move(n)) {} void HumanB::setWeapon(const Weapon& w) { weapon = &w; // 指向传入的引用对象,而非临时拷贝 } void HumanB::attack() const { if (weapon) { // 检查指针非空,避免野指针访问 std::cout << name << " attacks with his " << weapon->getType() << "\n"; } else { std::cout << name << " has no weapon!\n"; } }
2. HumanB的指针问题根源
你当前的setWeapon(Weapon w)是值传递,会创建一个Weapon的临时拷贝,函数结束后该拷贝立即销毁,此时weapon指针指向的是已释放的内存(野指针),后续访问会导致未定义行为(输出乱码、崩溃等)。
解决核心是将参数改为引用const Weapon& w,让指针指向main函数中生命周期有效的club对象。此外,attack()函数中你错误输出了指针地址,而非调用getType()获取武器类型,这也是无法正确输出的原因。
3. 指针/引用的适用场景
引用:
- 适用场景:对象必须始终存在(不能为null)、生命周期长于当前对象、无需更换指向。比如HumanA,构造时必须绑定武器,且武器的生命周期与HumanA一致,用引用更安全,无需检查空指针,语法更简洁。
- 符合题目要求:完全匹配HumanA"构造时必须有武器"的语义。
指针:
- 适用场景:对象可以不存在(允许为null)、需要后期设置或更换指向。比如HumanB,支持先创建对象再绑定武器,指针可以初始化为
nullptr表示无武器状态,之后再指向有效对象。 - 符合题目要求:匹配HumanB"可后期设置武器"的语义。
- 适用场景:对象可以不存在(允许为null)、需要后期设置或更换指向。比如HumanB,支持先创建对象再绑定武器,指针可以初始化为
内容的提问来源于stack exchange,提问作者agile_flow
相关产品推荐
相关产品推荐

