简体   繁体   English

C ++面向对象的问题

[英]C++ object orientated issue

I am trying to learn C++ OOP and I made the follwing code: 我正在尝试学习C ++ OOP,并编写了以下代码:

main.cpp main.cpp中

#include <iostream>
#include <string>
#include "monster.h"
using namespace std;

int main(int argc, char** argv) {
    Monster monster("Wizard",150,50);
    Monster monster2("Gorgoyle",450,15);

    cout << monster2.getHealth() << endl;
    monster.attack(monster2);
    cout << monster2.getHealth() << endl;
}

monster.h monster.h

#ifndef MONSTER_H
#define MONSTER_H
#include <iostream>
#include <string>
using namespace std;

class Monster
{
public:
    Monster(string name_, int health_, int damage_);
    ~Monster();
    int attack(Monster opponet);
    int getHealth();
    string name;
    int damage;
    int health = 0;
    int getDamage();
    void setHealth(int health_);
    void setDamage(int damage_);
    void setName(string name);
    void doDamageToOpponent(Monster opponent);
    string getName();
};

#endif

monster.cpp monster.cpp

#include "monster.h"

Monster::Monster(string name_, int health_, int damage_) {
    health = health_;
    setDamage(damage_);
    setName(name_);
}

Monster::~Monster() { }

int Monster::attack(Monster opponent) {
    doDamageToOpponent(opponent);
}

void Monster::doDamageToOpponent(Monster opponent) {
    int newHealth = opponent.getHealth() - this->getDamage();
    opponent.setHealth(newHealth);
}

int Monster::getHealth() {
    return health;
}

int Monster::getDamage() {
    return damage;
}

void Monster::setHealth(int health_) {
    health = health_;   
}

void Monster::setDamage(int damage_) {
    this->damage = damage_;
}

void Monster::setName(string name_) {
    this->name = name_;
}

string Monster::getName() {
    return name;
}

Now my problem is that, when I run this code I expect to have monster2 object to have 400 health left, but it is still 450 :S 现在我的问题是,当我运行此代码时,我希望使monster2对象剩余400个生命值,但仍然是450:S

What must be done here in order to to so? 为此必须在这里做什么? I noticed that it can be 400 in doDamageToOppoenet but when it leaves that block, then it is still 450. Please help me! 我注意到在doDamageToOppoenet中它可以是400,但是当它离开那个块时,它仍然是450。请帮助我! Thanks. 谢谢。

You're passing objects by value : 您正在按值传递对象:

void Monster::doDamageToOpponent(Monster opponent) <- This should be by reference
int Monster::attack(Monster opponent) <- idem

that means: you're creating a new copy of the Monster object you meant to deal damage to in the functions you're calling, and then actually dealing that copy damage but leaving the original old object with the value untouched. 这意味着:您正在创建要在调用的函数中造成损坏的Monster对象的新副本,然后实际造成该副本损坏,但保留原始对象的值不变。

Signatures as follows would work instead: 如下签名可以代替:

void Monster::doDamageToOpponent(Monster& opponent)
int Monster::attack(Monster& opponent)

If you want to learn more about this, something to read on: Passing stuff by reference and Passing stuff by value 如果您想了解更多有关此内容的信息,请继续阅读: 通过引用 传递内容通过值传递内容

The reason is that functions attack and doDamageToOpponent are taking copies of arguments, because you pass them by value . 其原因在于功能attackdoDamageToOpponent正在服用的参数的拷贝,因为按值传递它们。 What happenes then is you change the copies of passed Monsters inside functions. 然后发生的是您在函数内部更改了传递的Monsters的副本 After functions return, these copies die (as they are local to functions) and nothing happens to original, interested parties. 函数返回后,这些副本将消失(因为它们在函数中是本地的),并且原始的,感兴趣的各方不会发生任何事情。

Try instead pass the argument by reference. 尝试改为通过引用传递参数。 Reference works as if it was the original variable. 引用就像原始变量一样工作。 Consider: 考虑:

int a = 0;
int &refa = a; /* refa acts as real "a", it refers to the same object "a" */
int b = a;     /* this is your case */
b = 6;         /* b will be changed, but "a" not */
refa = 6;      /* a is changed, really "a", refa is just different name for "a" */

Try: 尝试:

int Monster::attack( Monster &opponent){
    doDamageToOpponent( opponent);
}

void Monster::doDamageToOpponent( Monster &opponent){
    int newHealth = opponent.getHealth() - this->getDamage();
    opponent.setHealth( newHealth);
}

You are passing the opponent by value, ie, the function: 您通过值传递对手,即函数:

int Monster::attack(Monster opponent);

will actually receive a copy of the opponent and modify that copy. 实际上会收到对手的副本并修改该副本。 Every time you have a function that modifies some object you need to pass the object to be modified by reference or pass a pointer to it, eg, 每次您拥有修改某些对象的功能时,都需要通过引用传递要修改的对象或将指针传递给它,例如,

int Monster::attack(Monster& opponent);

or 要么

int Monster::attack(Monster* opponent);

I recommend using const T& for input parameters and T* for output parameters, so in this case, the latter form. 我建议对输入参数使用const T& ,对输出参数使用T* ,因此在这种情况下,使用后一种形式。 The reason why I recommend the latter for output parameters is because it makes it more explicit to the caller: 我之所以推荐后者作为输出参数的原因是因为它使调用者更清楚:

monster.attack(&monster2); // passing a pointer: monster2 will be modified.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM