Trouble passing variables by reference. I think?

Hello all! As always, thanks in advance.
Im trying to make a text based game in C++, attempting to store player data inside the
Player class and modify it from other classes/functions.

The <setClass> function in the <Classes> class should assign values to <Classes> private member variables then pass those values to private member variables of the <Player> class.

When the displayPlayer function runs for the second time it should display the players "class" name, along with the stats to go along with his "class".

Needless to say this doesn't happen, nothing happens. I'm assuming its
something to do with me not passing by reference properly but I just learned
about referencing recently so try to keep it simple for me, I have a hard time
understanding programmer lingo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "stdafx.h"
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;

//Player class
class Player {
public:
	void setPlayerName(string& x) {
		name = x;
	}
	void setPlayerClass(string& x, int& y, int& z) {
		classname = x;
		stats[0] = y;
		stats[1] = z;
	}

	//Bonus question? Whats a better way then making a bunch of tedious 
        //return statements?
	//Tried returning multiple values but couldn't
	//figure out how to assign them to the <displayPlayer> function.
	string& getPlayerName() {
		return name;
	}
	string& getPlayerClassName() {
		return classname;
	}
	int& getPlayerStats0() {
		return stats[0];
	}
	int& getPlayerStats1() {
		return stats[1];
	}
	int& getPlayerStats2() {
		return stats[2];
	}
	//^

	//PRIVATE MEMBERS
private:
	string name, classname;
	int stats[3] = {};
};

//Classes class
class Classes {
public:
	string cName;
	int cStats[2] = {};

	void setClass(int x) {
		Player player;
		if (x == 1) {
			descendantClass();
			//^Modifies values of <cName> and <cStats> variables

			player.setPlayerClass(cName, cStats[0], cStats[1]);
			//^This should pass the modified values of <cName>, and 
                        //<cStats> to the <classname> and <stats> variables in the 
                        //<Player> class.
			//<cName> doesnt appear to succesfully assign its value to <classname>(in 
                        //Player class)
                        //<cStats> also doesnt appear to succesfully assign its 
                        //value to <stats>(in Player class).
		}
		else if (x == 2) {
			shadeClass();
			player.setPlayerClass(cName, cStats[0], cStats[1]);
		}
		else if (x == 3) {
			wandererClass();
			player.setPlayerClass(cName, cStats[0], cStats[1]);
		}
	}

	void descendantClass() {
		cName = "Descendant";
		cStats[0] = { 120 };
		cStats[1] = { 50 };
	}
	void shadeClass() {
		cName = "Shade";
		cStats[0] = { 100 };
		cStats[1] = { 75 };
	}
	void wandererClass() {
		cName = "Wanderer";
		cStats[0] = { 80 };
		cStats[1] = { 100 };
	}
private:
};

//displayPlayer function
void displayPlayer(Player& player) {
	string pName;
	string pClassName;
	int pStats[3];

	pName = player.getPlayerName();
	pClassName = player.getPlayerClassName();
	pStats[0] = player.getPlayerStats0();
	pStats[1] = player.getPlayerStats1();
	pStats[2] = player.getPlayerStats2();

	cout << "\nName = " << pName << endl;
	cout << "Class = " << pClassName << endl;
	cout << "HP    = " << pStats[0] << endl;
	cout << "Ess   = " << pStats[1] << endl;
	cout << "XP    = " << pStats[2] << endl;
}

//MAIN FUNCTION
int main()
{
	int input;
	string str;

	Player pObj;
	Classes cObj;

	cout << "What is your name?\n" << endl;
	 cin >> str;
	pObj.setPlayerName(str);//Sets <name>(in Player class) = <str>
	displayPlayer(pObj);//Displays current player data(taken from <Player> 
                            //class.
	cout << "\nWelcome, " << pObj.getPlayerName() << endl;
	cout << "\nWich class will you chose?" << endl;
	cout << "1 = Descendant" << endl;
	cout << "2 = Shade" << endl;
	cout << "3 = Wanderer\n" << endl;
	 cin >> input;
	cObj.setClass(input);//Sets class data(in Classes class(to be passed to 
                                      //Player class)) but doesnt work.
	displayPlayer(pObj);
}
Last edited on
Look at this snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	void setClass(int x) {
		Player player;
		if (x == 1) {
			descendantClass();
			//^Modifies values of <cName> and <cStats> variables

			player.setPlayerClass(cName, cStats[0], cStats[1]);
			//^This should pass the modified values of <cName>, and 
                        //<cStats> to the <classname> and <stats> variables in the 
                        //<Player> class.
			//<cName> doesnt appear to succesfully assign its value to <classname>(in 
                        //Player class)
                        //<cStats> also doesnt appear to succesfully assign its 
                        //value to <stats>(in Player class).
		}


Do you realize that player is local to this function? Once the function ends this variable no longer exists.

Perhaps you either need an instance of Player in your Classes class or Classes should be inheriting from Player.



First of all a few coding habits you should stick to:

1) If a field in a class (i.e.: private/protected/public) is not used omit it, for example on line 94 the private keyword can be removed.

2) Try to avoid get and set methods like the plague, because you can break encapsulation without realizing it like you did in the code above. for example all of these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       string& getPlayerName() {
		return name;
	}
	string& getPlayerClassName() {
		return classname;
	}
	int& getPlayerStats0() {
		return stats[0];
	}
	int& getPlayerStats1() {
		return stats[1];
	}
	int& getPlayerStats2() {
		return stats[2];
	}

if someone will type getPlayerStats2() = 5; than stats[2] will now be equal to 5 which breaks the purpose of the private section as it can be easily changed by anyone from the outside and in this case is equal to just making all of your private members public.

3) from the same example of point 2 when returning a built in value prefer to return by value, in your case int and not int& for example or const int& so that the private section cant be changed.

4) always divide your code into .cpp and .h files (an exception being templated classes)

i would recommend you learn from : http://www.learncpp.com/ as it is beginner friendly and explains everything in depth.

By the way i have some free time atm so i'l write a commented fix to your code so you can use it as a reference to future code. I will post it shortly.

#EDIT:
5) use the array.h library insted of c arrays its much safer and has many useful features

6) Lastly the names must be easily understandable, in this case cStatsand pStats are vague and when reading the code i cant figure out what each index of stats means up until the displayPlayer function which shows what each index means.
a better approach would be to make separate variables with descriptive names.
Last edited on
Here's the solution I came up with:

Game.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef GAME_H
#define GAME_H

#include <iostream>
#include <string>

//its okay to use struct's as data aggregates
struct ClassData
{
	int         health_;
	std::string name_;
	int         ess_; //I didn't really understand what the abbreviation means 
};

ClassData createClass(int choice); 

class Player
{
public:
	Player(const ClassData& class_data, std::string name, int experience = 0) :
		class_data_( class_data ), player_name_{ name }, experience_{ experience } {}

	/*
	Uncomment this portion if you dont understand the constructor above.
	Although I highly recommend learning about constructor initializer lists.
	Player(const ClassData& class_data, std::string name, int experience = 0) {
		class_data_    = class_data;
		experience_    = experience;
		player_name_ = name;
	}
	*/

	void showData();

private:
	std::string player_name_;
	ClassData   class_data_;
	int         experience_;
};

#endif  


Game.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "Game.h"

namespace {
	enum Classes { //I'l leave it enum inside of a namespace for simplicity but look up <enum class> keyword 
		Descendant = 1, //by default would be 0
		Shade,
		Wanderer
	};
}

void Player::showData()
{
	std::cout << "Player name: "  << player_name_            << '\n'
		        << "Player class: " << class_data_.name_       << '\n'
		        << "HP: "           << class_data_.health_     << '\n'
		        << "Ess: "          << class_data_.ess_        << '\n'
		        << "XP: "           << experience_             << '\n';
}

ClassData createClass(int choice)
{
	switch (choice) {
	case Descendant:
		return { 120, "Descendant", 50 };
		break;
	case Shade:
		return{ 100, "Shade", 75 };
		break;
	case Wanderer:
		return{ 80, "Wanderer", 100 };
		break;
	default:
		std::exit(EXIT_FAILURE); //meaning that the user entered an invalid class
	}
}


source.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "Game.h"

int main()
{
	int         choice;
	std::string name;

	std::cout << "What is your name?\n";
	std::getline(std::cin, name);

	std::cout << "\nWelcome, " << name << '\n'
		        << "Wich class will you chose?\n"
		        << "1 = Descendant\n"
		        << "2 = Shade\n"
		        << "3 = Wanderer\n";

	std::cin >> choice;
	Player player(createClass(choice), name);

	player.showData();
	return 0;
}



A few challenges you can put to yourself :
-Try implementing an operator << overload to the player class so that:
std::cout << player; would compile and run.
-change std::exit(EXIT_FAILURE); with throw std::runtime_error and handle the error in main (logging the error in notepad would be added difficulty)
Last edited on
Thank you jlb, figured out what I was doing wrong.

Thank you Globaltourist for telling me whatsup, nice to see replies like that its going to be incredibly useful major props to you.
Topic archived. No new replies allowed.