类属性不包含值
Class properties not holding values
我在一个基于文本的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;
}
更新评论中提出的问题
- 要解决在设置新值的情况下值仍保留为
150
的特定问题,将返回类型转换为reference
就足够了
为什么要返回参考作品因为,无论何时调用getJogador()
的原始版本,对象的副本都是创建。即使你正在改变它的价值,你实际上更改创建的临时对象的值,而不是原始对象的值一
因此,由于您的意图是修改原始对象,我们需要访问原始副本,而不是其临时副本。Reference
为在这种情况下,更好的机制(pointer
是另一种机制,但不如reference
安全) 现在谈谈我为什么建议
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
类的状态,因此,如果该方法确实试图修改状态,编译器可能会执行某些优化,并阻止成功编译。
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 如何在for循环中包含两个索引值的测试条件
- 范围 v3 可以包含初始值设定项列表的工作吗?
- C++17:使用 std::optional 来评估枚举是否包含值
- 如何在两个列表中比较和获取非包含值
- Boost::p tree - 访问列表中包含的属性树节点
- 只有Arduino的第一个对象在包含在另一个对象的集合/数组中时会丢失其数据属性值
- 如何知道unordered_map<T*>包含值?
- 为什么我不能声明同时具有模板容器和模板包含值的类型?
- 类属性不包含值
- 从DLL加载派生类时不包含派生属性
- 包含"random"值的类的数组属性(通过另一个类的指针访问时)
- 如何按一个值属性对海量地图进行排序
- expat是否包含分隔属性值的引号
- 包含值地址的字符串 ->该值的指针
- 仅当数组中尚未包含值时,才向数组添加值
- 将包含字符串属性的结构读取/写入二进制文件
- 如何找到包含值及其在 c++ 中出现的向量的分位数
- 提升::变体与包含值的比较
- 为什么在编组之后,数组中只有一个元素包含值