Reputation: 3
I'm pretty new to C++, but this has got me stumped. I'm working on the base code for an RPG, but this one character in the class has got me stumped. I've isolated the pieces at issue here (there's a good 1000 lines cut out), and the problem remains.
Here's the class and header for the program:
#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;
}
This next part that has me scratching my head. I started the following code:
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;
}
Now as far as I can tell, there's nothing wrong with any of this - the (GCC) compiler doesn't complain, and it works just fine up to a point. But if I run it, I get the following output:
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.
Worse than that, if I choose option "2" the output is the same only when it makes no sense:
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.
In other words, the expected output goes badly wrong somewhere between the last line of PlayerCharacterCreation()
, and the very next line of the PlayerCreationTest()
.
As far as I can tell, though, the "character" class should stay the same between functions, not change all willy-nilly like this.
I hope that's enough for someone to figure out what I'm doing wrong, but I was toying with it a little and managed to change the output character even more.
By adding an "srand(0)" line at the beginning of the main function, I can change the '@' to a 'y' for both options 1 and 2.
By adding a "GenderTest()" line at the beginning of the main function, I can change the '@' to a 'F', for both options. If I add both lines, only the one immediately above the "PlayerCreationTest()" line seems to matter. Which is odd, because the full code always returns an 'l' (lowercase L) instead of '@', and the main function is exactly the same as written above.
Upvotes: 0
Views: 120
Reputation: 24259
void PlayerCharacterCreation(character Player)
Inside this function, Player
is a local instance of character
into which the calling parameter is copied. Consider the following:
#include <iostream>
void f1(int x) {
x++;
}
void f2(int i) {
i++;
}
int main() {
int i = 0;
f(i);
std::cout << i << '\n';
}
We know that the output from this will be '0', because f1::x
and f2::i
are their own independent variables copied from our source parameter.
If you want to pass a specific instance of a variable rather than a copy of it, you need to provide a pointer or a reference.
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);
Example:
#include <iostream>
int f1(int& param) {
param++;
}
int main() {
int i = 0;
f1(i);
std::cout << i << '\n'; // outputs 1
}
Upvotes: 1
Reputation: 48968
As far as I can tell, though, the "character" class should stay the same between functions, not change all willy-nilly like this.
Well, you're wrong. They do stay the same, because they are seperate variables. PlayerCharacterCreation
creates a local character
(a copy of Test
), and at the end of the function, the object is destroyed.
The original character
that you passed to PlayerCharacterCreation
never changed, and you get some weird output because the gender was never set for that character
.
The Player
in PlayerCharacterCreation
is a totally new character
, it is not Test
:)
If you want to modify the character
passed to PlayerCharacterCreation
, you have to pass it by reference (there are some other ways too, like passing a pointer, returning Player
, but that's the best one):
void PlayerCharacterCreation(character& Player);
^^^
reference
Upvotes: 2