【问题标题】:Class object (char) changes after function类对象(char)在函数后发生变化
【发布时间】:2016-08-20 04:04:20
【问题描述】:

我对 C++ 还很陌生,但这让我很困惑。我正在编写一个 RPG 的基本代码,但是班上的这个角色让我很难过。我已经在这里隔离了有问题的部分(剪掉了 1000 行),但问题仍然存在。

这是程序的类和标题:

#include <iostream>
#include <cstdlib>
using namespace std;

unsigned long errorcount;
// I know this is bad coding, but it's not going to be in the end product...

class character {
public:
  void setgender(char newgender);
  char getgender() const;
private:
  char gender;
};

void character::setgender(char newgender) {
  switch (newgender) {
  case 'M': gender = 'M'; break;
  case 'F': gender = 'F'; break;
  default: gender = '0'; errorcount++; break;
  }
  std::cout << "\nDuring setgender function: " << gender;
  return;
}

char character::getgender() const {
  std::cout << "\nDuring getgender function: " << gender;
  return gender;
}

下一部分让我摸不着头脑。我开始了以下代码:

void PlayerCharacterCreation(character Player) {
  string newgender;
  while(true) {
    std::cout << "\nAre you male or female?" << "\n1. Male" << "\n2. Female" << "\n::";
    std::cin >> newgender;
    if (newgender == "1") { Player.setgender('M'); break; }
    if (newgender == "2") { Player.setgender('F'); break; }
    std::cout << "\nInvalid response.  Try again.";
  }
  std::cout << "\nAfter setgender function: " << Player.getgender();
}

void PlayerCreationTest() {
  character Test;
  PlayerCharacterCreation(Test);
  char playergender = Test.getgender();
  if (playergender != 'M' && playergender != 'F') { errorcount++; }
  std::cout << "\nAfter getgender function: " << playergender;
  std::cout << "\n\nOUTPUT BEGINS NOW\nGender: " << playergender << "\n";
  std::cout << "OUTPUT ENDS.  Total Errors: " << errorcount << ".";
  return;
}

int main() {
  PlayerCreationTest();
  return 0;
}

现在据我所知,这没有任何问题 - (GCC) 编译器不会抱怨,而且在某种程度上它工作得很好。但是如果我运行它,我会得到以下输出:

Are you male or female?
1. Male
2. Female
1
During setgender function: M
During getgender function: M
After setgender function: M
During getgender function: @
After getgender function: @
OUTPUT BEGINS NOW    
Gender: @
OUTPUT ENDS.  Total Errors: 1.

更糟糕的是,如果我选择选项“2”,则只有在没有意义的情况下输出是相同的:

Are you male or female?
1. Male
2. Female
2
During setgender function: F
During getgender function: F
After setgender function: F
During getgender function: @
After getgender function: @
OUTPUT BEGINS NOW
Gender: @
OUTPUT ENDS.  Total Errors: 1.

换句话说,预期的输出在PlayerCharacterCreation() 的最后一行和PlayerCreationTest() 的下一行之间出现了严重错误。

据我所知,“字符”类应该在函数之间保持不变,而不是像这样随意更改。

我希望这足以让某人找出我做错了什么,但我只是在玩弄它并设法进一步改变输出字符。

通过在主函数的开头添加“srand(0)”行,我可以将选项 1 和 2 的“@”更改为“y”。

通过在主函数的开头添加“GenderTest()”行,我可以将“@”更改为“F”,两个选项。如果我同时添加这两行,那么只有“PlayerCreationTest()”行上方的那一行似乎很重要。这很奇怪,因为完整的代码总是返回一个 'l'(小写 L)而不是 '@',而且 main 函数和上面写的完全一样。

【问题讨论】:

  • 阅读“按价值”和“按参考”的概念。 PlayerCharacterCreation() 的参数是按值传递的,而您期望的行为是由通过引用传递的参数组成的。

标签: c++ function class char


【解决方案1】:

不过,据我所知,“字符”类在函数之间应该保持不变,而不是像这样随意更改。

好吧,你错了。它们确实保持不变,因为它们是单独的变量PlayerCharacterCreation 创建一个本地的characterTest 的副本),并在函数结束时销毁该对象。

您传递给PlayerCharacterCreation 的原始character 从未改变,并且您得到一些奇怪的输出,因为从未为该character 设置性别。

PlayerCharacterCreation 中的Player 是一个全新的character,它不是Test :)

如果你想修改传递给PlayerCharacterCreationcharacter,你必须通过引用传递它(还有一些其他的方法,比如传递一个指针,返回Player,但这是最好的方法):

void PlayerCharacterCreation(character& Player);
                                     ^^^
                                  reference

【讨论】:

  • 谢谢!这就是我所需要的。我肯定还有一段路要走。
【解决方案2】:
void PlayerCharacterCreation(character Player)

在此函数中,Playercharacter 的本地实例,调用参数复制到该实例中。考虑以下几点:

#include <iostream>

void f1(int x) {
    x++;
}

void f2(int i) {
    i++;
}

int main() {
    int i = 0;
    f(i);
    std::cout << i << '\n';
}

我们知道它的输出将为“0”,因为f1::xf2::i 是从我们的源参数复制而来的它们自己的独立变量。

如果要传递变量的特定实例而不是其副本,则需要提供指针或引用。

void by_pointer(Character* player) {
    if (player == nullptr) {
        error_handling();
    }
    player->do_thing();
}
by_pointer(&player);

void by_reference(Character& player) {
    player.do_thing();
}
by_reference(player);

例子:

#include <iostream>

int f1(int& param) {
    param++;
}

int main() {
    int i = 0;
    f1(i);
    std::cout << i << '\n';  // outputs 1
}

【讨论】:

  • 非常感谢!我知道这一定很简单。完美运行!
猜你喜欢
  • 1970-01-01
  • 2020-07-06
  • 2021-06-04
  • 2015-12-15
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多