将成员变量存储为引用,vs指针



我正在研究一些问题,以更好地完善我对指针、引用和最佳实践用法的工作知识。这是我目前正在解决的一个问题,我需要对我的解决方案进行一些调整。

问题陈述:

创建一个武器类,它有一个类型字符串,和一个getType返回一个const引用到这个字符串。也有一个setType

现在,创建两个类HumanA和HumanB,它们都有武器、名称和一个attack()函数,该函数显示如下内容:

让下面的代码产生带有"粗刺棒"的攻击;然后是"其他类型的俱乐部"。在两个测试用例中:

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()中给出的代码块进行一些轻微的修改,以使其工作-这显然不是很好。虽然我的确实产生预期的输出,但我不确定我需要改变什么才能使给定的main()按原样工作。我不明白你怎么能改变你如何储存武器而不改变它是如何在main()中传递的。

目前为止我有什么:

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"; //I cannot get cout to print the value of the address that weapon points to
}
void HumanB::attack()
{
std::cout << name << " attacks with his " << weapon << "n"; //I cannot get cout to print the value of the address that weapon points to
}

Problem语句的设置是为了让您考虑引用和指针以及它们的不同特征。它还显式地描述了一些需求,但提供了一个不允许修改的main函数。这增加了额外的隐式需求,以便您可以学习确定这些需求并将新代码放入现有代码中。

由于clubWeapon对象的武器类型在HumanA对象初始化后发生了变化,并且该变化需要影响HumanA的操作,因此需要引用或指针成员来保持与原始对象的连接。普通的数据成员不会产生这种行为。HumanB的情况类似,但正如OP在评论讨论中正确地总结的那样,"引用成员永远不能更改"。所以在这种情况下,由于HumanB必须更改它(因为它最初从未设置过),因此您不能拥有引用成员…这意味着这里唯一的其他选择是使用指针。">

正如user4581301所指出的,引用的这一相同特性经常使引用成员的使用出现问题。它"使类实例的赋值变得复杂或不可能"。这正是因为"你不能改变引用所指向的"。在OP中的问题中,这没有出现,但如果需要扩展代码,则可能成为一个问题。在其他情况下,这也是一个问题。

所以类HumanA可以使用引用或指针作为其武器成员,尽管指针可能是更好的选择。HumanB必须使用指针。

当使用指针,但将其设置为对象被延迟时,应将其初始化为nullptr。否则,将无法检查它并确定它当前是否指向一个对象。

OP的剩余挑战(见评论)是实现HumanB的setWeapon()方法而不修改提供的main()。setWeapon()需要接受一个参数来设置HumanB的指针成员。按值传递对象将创建一个副本,并断开到原始对象的所需链接。这就留下了传递指向对象的指针或引用。使用指针需要(禁止)更改main()。因此,我们已经从现有代码中派生出了隐式接口规范,即HumanB的setWeapon()通过引用获取其参数。

最新更新