I've searched but haven't been able to get what I want...
I'm doing a little game. And I got this struct
that contains the player details.
struct Player
{
string name;
int level;
int exp;
int hp; // life
int mp; // mana
int shield;
};
And when in the menu, the user chooses to start a new game, it goes to this function:
int StartNewPlayer(string name)
{
Player player;
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
*pass/return the struct here*
}
Then I have a function that prints the game board, and where I should use the data from the new player struct, for example:
void game_board ()
{
cout << "Hello!" << player.name;
(...)
}
Finally, somewhere in main
I have:
int main ()
{
StartNewPlayer(new_game());
game_board();
}
that calls all the functions above.
But I can't figure it out... I tried references, pointers without luck.. I need some help here please...
How about this?
Player StartNewPlayer(string name)
{
Player player;
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
return player;
}
void game_board(Player player)
{
cout << "Hello!" << player.name;
(...)
}
int main ()
{
Player player = StartNewPlayer(new_game());
game_board(player);
}
Do not create extra copies of the data with complex datatypes by using pass-by-value
Use pointers instead to pass the address of the variable that can be modified in the function. The changes will be reflected in the caller's function as well.
void StartNewPlayer(string name, Player *player)
{
player->name = name;
player->level = 1;
player->exp = 0;
player->hp = 20;
player->mp = 5;
player->shield = 0;
}
void game_board(Player* player)
{
cout << "Hello!" << player->name;
(...)
}
int main ()
{
Player player;
StartNewPlayer(new_game(), &player);
game_board(&player);
}
Alternative using pass-by-reference:
If you're a fan of references, (which is just a clever compiler-trick that makes use of pointers internally again):
void StartNewPlayer(string name, Player& player)
{
player.name = name;
player.level = 1;
player.exp = 0;
player.hp = 20;
player.mp = 5;
player.shield = 0;
}
void game_board(Player& player)
{
cout << "Hello!" << player.name;
(...)
}
int main ()
{
Player player;
StartNewPlayer(new_game(), player);
game_board(player);
}
I would suggest returning a pointer to a Player struct. If you return a "reference" like you are doing right now, it will call the copy constructor of Player which can lead to further complications.
Normally, at the end of StartNewPlayer(...), the Player you declared there will cease to exist as the object scope will end, so when you return it, the c++ compiler gets that you want to keep the object alive and will create a copy for you, invisibly. If you return a pointer to it, you really are returning the object you allocated in your function.
Suppose that you have pointers in your Player structure, such as
struct Player
{
int level;
char* name; //lets assume you did it like that
}
When you are returning the Player, the int will be copied, but the char* will not. ints are easy to handle while char* need all kind of tricky functions like strlen
and strncpy
. The more complex your Player struct becomes, the more problem you will face by using the default copy constructor.
Another solution would be to declare a copy constructor yourself for the Player struct ( really, you could use classes since they are mostly interchangeable in c++ ).
Player(const Player& p)
{
name = p.name;
level = p.level;
// and so forth
}
So I would use
Player* StartNewPlayer(std::string name)
{
Player* player = new Player();
player->name = name;
player->level = 1;
// snip
return player;
}
At the end of your program, be sure to delete player
otherwise you will have a memory leak