Need Help with C++ Exception

Started by
7 comments, last by rip-off 16 years, 2 months ago
I'm following a video tutorial for a text-based RPG called WrathLands and my GetGold() function for my player is causing problems.

int Player::GetGold()
{
	return gold;
}

The exception occurs here

void Inn(Player* thePlayer)
{
	cout << "You stand in an almost vacant inn. Except for an old man standing behind the\ncounter,";
	cout << " there is no one else currently staying here.\n\n";
	cout << "You walk over to the old man. He grins, delighted to see a visitor.\n";
	cout << "Hello and welcome, would you like to stay in my inn for only 10 gold coins?\n";

	char answer = 'm'; 

	while (answer != 'y' && answer != 'n')
	{
		cout << "Stay? (10 gold) y/n\n";
		cin >> answer;
	}

	cout << endl;

	if (answer == 'y')
	{
                 //Exception occurs here
		if (thePlayer->GetGold() >= 10)
		{
			thePlayer->SpendGold(10);
		cout << "You find a nice bed and fall fast asleep.";
		Wait();
		cout << "\nHP and MP restored\n";
		cout << "HP: " << thePlayer->GetMaxHP() << " MP: " << thePlayer->GetMaxMana() << "\n";
		thePlayer->SetHP(thePlayer->GetMaxHP());
		thePlayer->SetMana(thePlayer->GetMaxMana());
		Wait();
		}

		else
		{
			cout << "It looks like you don't have enough gold.\n";
			Wait();
			answer = 'n';
		}
	}

	if (answer == 'n')
	{
		cout << "You turn around and walk out of the inn\n";
		Wait();
	}

}

Any way to solve this? Thanks.
Advertisement
What exception?
Quote:Original post by jyk
What exception?


When I respond with a 'y'. An exception occurs during this.
Post the error please.
Quote:Original post by Justin Rebuilt
Post the error please.


Unhandled exception at 0x00412496 in WrathLands.exe: 0xC0000005: Access violation reading location 0x00000028.

Then it points to my GetGold() function.

it occurs when i enter 'y' for my choice
Is thePlayer non-null? Does it point to a valid Player instance?

You can check for the former by adding:
assert(thePlayer);
At the top of your Inn() function. There really is no way to verify the latter, which is one of the dangers of using raw pointers in C++. (You'll learn more about this - and about debugging in general - as you progress.)

If your project isn't too large, you might just go ahead and post the code in its entirety so we can see what else is going on.
My guess is that you have a bad "player" pointer. You should check with your debugger to be sure.

You may need to either allocate a new player object using "new Player;". The alternative would be to allocate the player on the stack (or by value in an object).

The first step is to stop using pointers unless you want "optional" arguments. Use references instead.

void Inn(Player &thePlayer){	// ...	if (answer == 'y')	{                 //Exception occurs here		if (thePlayer.GetGold() >= 10)		{			thePlayer.SpendGold(10);		cout << "You find a nice bed and fall fast asleep.";		Wait();		cout << "\nHP and MP restored\n";		cout << "HP: " << thePlayer.GetMaxHP() << " MP: " << thePlayer.GetMaxMana() << "\n";		thePlayer.SetHP(thePlayer.GetMaxHP());		thePlayer.SetMana(thePlayer.GetMaxMana());		Wait();		}		// ...}


I must also point out that your manipulation of private member variables is bad style. Instead of manually calling Set*() and Get*() on the player, give the actions you are doing names and implement these instead as member functions.

class Player{public:   void restore(); // or sleep, or whatever   void loseHp( int amount );   void castSpell( const Spell & );   void printStats( std::istream & );};


In a well written program, you will have very few "set" functions. "get" functions aren't quite so bad, as sometimes you need to inspect an object. Still, replacing these kind of functions with domain specific functions is far better.
Quote:Original post by jyk
Is thePlayer non-null? Does it point to a valid Player instance?

You can check for the former by adding:
assert(thePlayer);
At the top of your Inn() function. There really is no way to verify the latter, which is one of the dangers of using raw pointers in C++. (You'll learn more about this - and about debugging in general - as you progress.)

If your project isn't too large, you might just go ahead and post the code in its entirety so we can see what else is going on.


Oh, I didn't point it to a player...

My game runs smoothly now. Thanks for your help jvk! :)

Ripoff, so you're implying that it's better to avoid having too many functions in a class?
No, that is not the point at all. If anything I'm arguing for more functions.

The point of exposing object functionality with public member functions is so that external objects don't mess with private member variables. But if all you do is add get/set routines for all those members, you haven't gained anything, and your code is a lot more verbose.

When you think of a player, what kind of actions can you see it making? Does it sleep, heal, cast spells? Or does is it just a collection of variables that you can set or get. I think the former makes for code that reads better.
class Player {/*...*/};class Monster {/*...*/};void fight(Player &player, Monster &monster){    while( player.alive() && monster.alive() )    {        monster.takeDamage(player.attack());        player.takeDamage(monster.attack());    }    if( player.dead() )    {        std::cout << "You died, sorry.\n";    }    else    {        std::cout << "You beat up the " << monster.name() << '\n';        player.addExperience( monster.experienceValue() );    }}

As opposed to:
class Player {/*...*/};class Monster {/*...*/};void fight(Player &player, Monster &monster){    while( player.getHP() > 0 && monster.getHP() > 0 )    {        monster.setHP(monster.getHP() - player.getAttack());        player.setHP(player.getHP() - monster.getAttack());    }    if( player.getHP() < 0 )    {        std::cout << "You died, sorry.\n";    }    else    {        std::cout << "You beat up the " << monster.getName() << '\n';        player.setExperience( player.getExperience() + monster.getValue() );    }}


Can you see?

This topic is closed to new replies.

Advertisement