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

成员变量存为引用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();
}
}

我的问题

  1. 希望不修改给定的main()代码完成实现;
  2. 当前HumanB类存在指针相关错误,无法正确输出武器类型;
  3. 明确何时适合将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"可后期设置武器"的语义。

内容的提问来源于stack exchange,提问作者agile_flow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:05:19