使用object作为参数调用成员函数

时间:2016-10-06 19:59:49

标签: c++ object

我目前正在和我的大学一起学习中级c ++课程,而且我们刚刚完成了课程/多态,因此我决定开展自己的一个小项目。这不是家庭作业,我认为这样可以解决问题。

所以我使用SFML做了一点空闲"游戏。这包括一个实体类,一个用于武器的类和一个用于装甲的类。我有2个实体,作为玩家和"其他"或敌人。到目前为止,一切都很好,但是当我尝试使用参数作为另一个实体调用实体类的成员函数时,我遇到了麻烦。 这是两个函数

/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity other) {
    other.decreaseHP(5);
    if (other.getCurrentHP() <= 0) {
        killEntity(other);
    }
}

/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity other) {
    if (other.getEntityType() == "Enemy") {
        other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
        addXP(other.getXP());
        //addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
        addGold(rand() % getEntityLevel() + getEntityLevel());

        // Increment the level of the entity to give them better armor/weapon
        other.incrementLevel();
        // Regenerate a weapon and armor for the enemy
        other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
        other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
    }
    else if (other.getEntityType() == "Player") {
        other.setXP(other.getXP() / 10);
        other.setCurrentHP(other.getMaxHP());
        other.refreshEntityInfo();
    }
}

目前,在主程序中,我将其称为

if (clock.getElapsedTime().asSeconds() >= 1.0f) {
    player.attackEntity(enemy);
    clock.restart();
}

想要代码要做的是每1秒,玩家将&#34;攻击&#34;另一个实体,是敌人。这将使另一个实体的健康点降低5,当其他实体的健康点降至1以下时,它将“杀死”#34;实体,授予玩家体验并重置其他实体的护甲和武器,这将为其提供新的统计数据。 但是, 正在发生什么,什么都不是。健康点不会减少。 显然我在这里做错了,因为它不起作用。

我测试过只在时间循环中单独调用reduceHP()方法,并且有效:

if (clock.getElapsedTime().asSeconds() >= 1.0f) {
    //player.attackEntity(enemy);
    player.decreaseHP(5);
    clock.restart();
}

但是我在使用attackEntity()方法之前提供的方式却没有。

这是reduceHP()方法。

/*
    Decreases the entity's current health by amount
*/
void Entity::decreaseHP(int amount) {
    setCurrentHP(getCurrentHP() - amount);
}

我是否需要传递其他实体对象作为参考?我是否以糟糕的方式处理这些功能?我该怎么接近这个?

编辑 - 所以我知道我刚发布了这个,但我更改了attackEntity()函数和killEntity()函数的参数,因此它通过引用获取实体对象,这似乎解决了解决方案。

/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity &other) {
    if (other.getEntityType() == "Enemy") {
        other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
        addXP(other.getXP());
        //addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
        addGold(rand() % getEntityLevel() + getEntityLevel());

        // Increment the level of the entity to give them better armor/weapon
        other.incrementLevel();
        // Regenerate a weapon and armor for the enemy
        other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
        other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
    }
    else if (other.getEntityType() == "Player") {
        other.setXP(other.getXP() / 10);
        other.setCurrentHP(other.getMaxHP());
        other.refreshEntityInfo();
    }
}

/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity &other) {
    other.decreaseHP(5);
    if (other.getCurrentHP() <= 0) {
        killEntity(other);
    }
}

然而,我的最后一个问题仍然存在:我是否以正确的方式解决这个问题?

3 个答案:

答案 0 :(得分:3)

签名void Entity::attackEntity(Entity other)会导致other成为该实体的副本。对other所做的任何更改都是attackEntity函数的本地更改。

如果您需要从源项目中保留更改,最直接的方法是通过引用传递other,将签名更改为:void Entity::attackEntity(Entity& other)

答案 1 :(得分:1)

鉴于此......

void Entity::attackEntity(Entity other) {

...然后这段代码

Entity x;
foo.attackEntity(x);

...将创建一个X的COPY,将其传递给attackEntity,后者会修改立即丢弃的本地副本。所以x保持不变。

在这种情况下,请使用按引用传递。

void Entity::attackEntity(Entity &other)

如果该方法不是要修改x,请改为使用pass by const引用:

bool Entity::isWithinRange(const Entitiy &other)

在编辑之后,是的,引用绝对是处理此问题的正确方法。按值(或作为指针)传递对象通常是代码“气味”。

答案 2 :(得分:-1)

检查你对等号运算符的使用,&#34; ==&#34;。 C ++并不像Java和C#那样处理字符串。引用的字符串(例如&#34; Enemy&#34;)分解为指针,因此比较变为&#34;该指针指向与另一个指针相同的地址,&#34;答案几乎总是&#34;没有。&#34;

您可以尝试使用std :: string类型,它定义了compare()方法,但一般来说,C ++字符串只比C字符串稍微友好一点。

您可能应该使用老式的C字符串比较函数,例如strcmp()。