类属性不包含值

Class properties not holding values

本文关键字:包含值 属性      更新时间:2023-10-16

我在一个基于文本的RPG游戏中工作,但当我将值设置为X变量时,当我再次访问该属性时,它处于默认值,我做错了什么吗?

class Game
{
private:
    bool podeAndar;
    bool estaBatalhando;
    Jogador _jogador;
    Mapa _mapa;
public:
    Game() { }
    Game(Jogador _j){
        _jogador = Jogador(_j.getNome());
        _mapa.LoadMapa();
        podeAndar = true;
        estaBatalhando = false;
    }
    ~Game(void)
    {
    }
    Jogador getJogador() {
        return _jogador;
    }
    void setJogador(Jogador v) {
        _jogador = v;
    }
}

我的"玩家"类

#pragma once
#include "Criatura.h"
#include <string>
class Jogador :
    public Criatura
{
private:
    int _cap;
public:
    Jogador(std::string nome)
    {
        setNome(nome);
        setCap(150);
    }
    Jogador() { }
    ~Jogador(void)
    {
    }
    int getCap(){
        return _cap;
    }
    void setCap(int v){
        _cap = v;
    }
}

它们是我的"Main"-当我设置值时,当我在调试器中跟踪它时,它会正确设置值,但当我再次访问game.getJogador().getCap()时,它的默认值为150。

int _tmain(int argc, _TCHAR* argv[])
{
     Jogador _player = Jogador("Kyore");
     Game game = Game(_player);
     while(true){
          std::cout << game.getJogador().getCap(); //print 150
          game.getJogador().setCap(100); //set cap to 100
          std::cout << game.getJogador().getCap(); //print 150 again
          break;
     }
}

Game类中,更改此

Jogador getJogador() {
        return _jogador;
    }

Jogador& getJogador() {
        return _jogador;
    }

并添加一个只用于读取的方法:

const Jogador& getJogador()const {
            return _jogador;
        }

更新评论中提出的问题

  1. 要解决在设置新值的情况下值仍保留为150的特定问题,将返回类型转换为reference就足够了
    为什么要返回参考作品因为,无论何时调用getJogador()的原始版本,对象的副本都是创建。即使你正在改变它的价值,你实际上更改创建的临时对象的值,而不是原始对象的值一
    因此,由于您的意图是修改原始对象,我们需要访问原始副本,而不是其临时副本。Reference为在这种情况下,更好的机制(pointer是另一种机制,但不如reference安全)
  2. 现在谈谈我为什么建议const member的新过载函数,返回一个const reference:这是为了向您强调,在不意外更改对象内部状态的情况下,仍然可以获取对象
    您的示例代码不会区分这两个getJogador()函数
    因此,要理解,请将这两个函数添加到Game class:

    void DontManipulate()const { std::cout<<getJogador().getCap(); }
    void Manipulate() { std::cout<<getJogador().getCap(); }

    看看你得到的编译器错误:-它应该会揭示差异
    此外,如果您在两个getJogador()函数中都std::cout一些消息,您应该能够找出差异。

问题出在getJogador()方法中。

在C++中,对象可以"按值"传递——这是程序(通常)将对象的原始数据复制到新位置的地方,而在C#和Java中,对象总是通过引用传递(不包括C#的struct,它们是按类似C++的值传递的)。C++将使用"复制构造函数"来执行此复制。如果代码中没有明确定义复制构造函数,C++将创建它,签名的形式为ClassName(ClassName& other);,默认的(非明确的)复制构造函数执行浅层的成员复制操作。

在您的情况下,getJogador方法返回Jogador实例字段数据的副本。

更改方法以返回引用或指针,如下所示:

Jogador& getJogador() const {
    return _jogador;
}

Jogador* getJogador() const {
    return &_jogador;
}

const修饰符通知编译器,此方法不打算修改Game类的状态,因此,如果该方法确实试图修改状态,编译器可能会执行某些优化,并阻止成功编译。