Class objects and allowing use globally

New to c++ and though it would of paid to spend alot more time on smaller projects and learns the basics, i have already leapt into developing an rpg, however as you can presume I have come a cropper with classes.

So far its fairly linear, presenting the player with switch cases on whether to start a new game, this comes up to our character creation function where, depending on the players choice of hero, an object of that class is defined with the name player inside the function

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
void H_arcane_descrip()
{
	string option;
	system("CLS");
	cout<<"Arcanist\n";
          cout<<"\n";
          cout<<"Arcanist's are dedicated scholars who have explored the mysteries of life and creation through the use of mana\n";
          cout<<"and various incantations. The knowledge they gathered from their studies allowed them to discover the power";
          cout<<"certain words held over the various strands of creation. Through reciting incantations, arcanists are able\n";
          cout<<"to incite life, creating vast and powerful abilities, allowing them to crush their enemies with their high\n";
          cout<<"intelligence and heavy damaging spells.\n";
          cout<<"\n";
		  cout<<"Is this the job you would like to choose? (y/n) \n";
		  cout<<"Selection:  ";
		  cin>> option;
		  cin.ignore();
		   if ( option == "y" || option == "Y" )
		   {
               //creates the player object with the code defined for an arcanist
			   Mage player;
			  
		 cout<<"\n";
		 cout<<"Finally, What is your name?\n";
		 cin>> player.name;
		 system("CLS");
				   }
}

with our arcanist class defined above this function
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
class Mage 
{
public:
	//constructor for my mage class, sets integers to a default state
	Mage();
	//name of the player
	string name;

	//temporary stats
	int current_health, current_mana, strength_plus, strength_minus, agility_plus, agility_minus, intelligence_plus, intelligence_minus, hit_plus, hit_minus, crit_plus, crit_minus, defence_plus, defence_minus, evasion_plus, evasion_minus;

	// calls the function which adds xp to the player, then checks whether or not the player has leveled, resetting xp and updating stats
	int addXP(int add);
	//the main function which holds all the player can do on his turn, attack, items, abilities
	void player_turn();
	// the function called within the main option to check player stats
	void player_stats();
	// the function called after each level up and during fights, updating the players base stats and any tempory stat affects
	void U_base_stats();
	//Function called which updates the current health of the player
	void U_health(int heal, int dmg);
	//the function called to look at player equipment, printing whats equipped and giving the options to unequip
	void player_equipment();

protected:
	//base stats handled by the job algortihm
	int health, mana, strength, intelligence, agility, hit, crit, defence, evasion;
   //level of character and curent xp stored 
   int lvl, xp, maxXP;
};


The issue that arises however is that I'm capable of calling any of the mage class functions, such as player.player_stats(); , as long as it is within the function the object was created in, which would be my void H_arcane_descrip function, otherwise the undeclared identifier error occurs as seen in the separate menu function.

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
void Menu ()
{
	int input;
	system("CLS");
	 cout<<"Main Menu\n";
	 cout<<"\n";
     cout<<"Explore (1)\n";
	 cout<<"Check Stats (2)\n";
	 cout<<"Inventory (3)\n";
	 cout<<"Check Eqipment (4)\n";
     cout<<"Save Game (5)\n";
	 cout<<"End Game (6)\n";
	 cout<<"\n";
	 cout<<"Selection:  ";
	cin>> input;
	cin.ignore();

	switch(input) {

	case 1:

		break;
	case 2:
		{
		player.player_stats();
		break;
		}
	case 3:
		break;
	case 4:
		break;
	case 5:
		break;
	case 6:
		break;
	default:
		cout<<"Incorrect Input, please try again \n";
	}
}


I presume that this is similar to functions within c++ , that if you try to call one before its been defined, it throws a wobbly. And because i'm trying to call an object which has only been declared in my H_arcane_descrip function, unless there is a way to make the object globally recognised.

help would be appreciated, as i expect the answer has something to do with including header files which i have not touched alot on.

tl:dr creating a player object from mage class in one function, can't call player object in any other functions

OK from briefly reading through I understand that u have a class Mage and then u have 2 functions Menu() and H_arcane_descrip() that want to be able to use the object(s) created by the Mage class right ?

The problem with the way u've written ur functions is that the Mage object, namely 'player' is not being passed into these functions and hence is unusable. One proper way would be to pass 'player' into the functions that want to access 'player's' members is by reference &. Let me illustrate using ints instead of class Mage:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
   int foo = 5;
   FuncFoo();
   return 0;
}

void FuncFoo()
{
   foo = 9;     //error 'foo' undeclared identifier
}


Remember that classes should be treated no differently from int, double, char or any other type.
Last edited on
I can get what your explaining as, in the case of the int variable, unless declared as global, it only stores the info for that function, however, as i haven't tread this water yet, i found a similar example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass
{
  // blabla
};
void foo(MyClass& obj)
{
    // class passed by reference
}
int main()
{
    MyClass myclass; // create an instance of the class
    foo(myclass); // pass it to another function
}


I take it from reading into it, and correct me if im wrong, an instance of myclass in this example is created, and then in the following line, passed by reference into the function Foo, where if we call Foo later which inside the argument contains (myclass) so foo(myclass); it will point back to our original object where ever we made it

so in my case it would be something like

mage player;
player_stat_check(player);

void player_stat_check (test& obj)
{
test.player_stats();
}


but then how would call the player_stat_check function without passing a seperate different object?


unless declared as global,

Yes this is 1 option but I was trying to deter u from using global variables since u don't have to. The problem is that Mage player just like int foo go out of scope. The best way to use player or int in a function is to pass them by either value or reference& or as a pointer*. For objects (like 'player') u normally want to use either reference (simple) or pointer (a little more complex). That way u don't actually send the whole object (which can be big and taxing on ur comp's memory) since it creates a copy of it just for the function.

I'm not sure what u mean...
but then how would call the player_stat_check function without passing a seperate different object?

U do want the player_stat_check for the player u've created dont u ?

Also, ur case is wrong. This is what it would/should be:
1
2
3
4
5
6
7
8
9
10
Mage player; //player object of type Mage created (same as int foo;)
player_stat_check(player); //checking player stats

//this function takes a reference of type 'Mage' 
//(just like 'void player_stat_check(int & foo) takes a reference of type 'int')
void player_stat_check (Mage & obj)  
{
obj.player_stats(); //'obj' the same as 'player' that was passed in
//the player_stats() that are accessed will be those from 'player'
}



Last edited on
sorry about the separate different object thing, just got confused by the example i found as it sounded like you had to first call the function with the object you wanted referenced within the arguments, and then a separate call to actually use the function.

the case you wrote clears it all up for me now as, in a weird way to me, reminds me of the keys used within a vector loop storing objects, as you pass the name of the object into the function and from there it finds it and calls out the object function you want.

I presume that in further cases if you then want to change values held within the objects, you just add additional arguments to get the values your inputting, and just use similar code to the player stats e.g obj.player_name = arg2; or call functions within the object that handle that

if you then want to change values held within the objects...

Use member functions within class Mage to change the values of ur Mage objects, not global functions that take a class Mage object....explained below...


Firstly, use standard class syntax. It'll make ur code much more readable and much less error prone. Member vars should be prefixed with m_. string name; should be private. Change ur 'protected' to 'private'. Add Get and Set methods to access the private members. U don't ever want to see ur private members being used outside of ur class. Most can be written inline like this if they are short:

1
2
3
4
5
6
7
8
9
class Mage 
{
public:
	int Get_Player_Health()                 {   return m_health;        };
        void Set_Player_Health(int newhealth)   {   m_health = newhealth;   };

private:
        m_health;
}:



Line 24 of void H_arcane_descrip() breaks encapsulation. U don't want to be accessing member 'name' directly like that.


Last edited on
Topic archived. No new replies allowed.