Sign in to follow this  

Need help with classes

This topic is 4589 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay I started to brush up on my knowledge of classes before I continued working on my SDL game. The simple test was to have two classes Aero(Hero) and Mon(Monster) which contain their attack and set stats functions abd have a class that held a function to display their health. Seemed simple enough but it doesn't always work out that way for me. I'm going to post my header and cpp files now and briefly tell you about them. Beigns.h
#ifndef Beings_H
#define Beings_H

class Aero
{
   public:   
      
      int Aattack;
      int Ahealth;
      
      void AeroAtk();
      void SetStats(int Ahealth, int Aattack);
      
      
   private:
           
           int AeroH;
           int AeroA;
           
           
}Aero;

class Mon
{
   public:
          
    int Mattack;
    int Mhealth;
          
    void MonAtk();      
    void SetMonStats(int Mhealth, int Mattack);
    
    
   private:
           
           
           int MonH;
           int MonA;
}Mon;

class ShowHealth
{
  public:    
             
             
   void ShowHealth();
   
   
  private: 
}health;    


#endif       





^Outlines the classes^ Beings.cpp
#include "Beings.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

void Aero::AeroAtk(int Aattack, int Mhealth)
{
     cout<<"Aero attacks!!!"<<endl;
     
     cout<<endl;
     
     Mhealth - Aattack;
     
     cout<<"Aero did "<<Aattack<<" damage!"<<endl;
     
     cout<<endl;
};

void Aero::SetStats(int Ahealth, int Aattack)
{
  AeroH = Ahealth;
  AeroA = Aattack;

};

void Mon::MonAtk(int Mattack, int Ahealth)
{
     cout<<"Mon attacks!!!"<<endl;
     
     cout<<endl;
     
     Ahealth - Mattack;
             
     cout<<"Mon did "<<Mattack<<" damage!"<<endl;
     
     cout<<endl;
     
};

void Mon::SetMonStats(int Mhealth, int Mattack)
{
     
   MonH = Mhealth;
   MonA = Mattack;
   
};


void ShowHealth::ShowHealth()
{
     return Ahealth;
     return Mhealth;
     
     cout<<"Aero Health: "<<Ahealth<<endl;
     cout<<"Mon  Health: "<<Mhealth<<endl;
     
     cout<<endl;
     
};            





^Defines the class functions^ main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include "Beings.h"

using namespace std;

int main(int argc, char *argv[])
{
    int turn = 1;
    Aero.SetStats(30,5);
    Mon.SetMonStats(20,3);
    
    while(Ahealth && Mhealth != 0)
    {
      if(turn == 1)
      {
        Aero.AeroAtk();
        health.ShowHealth();
        turn = 2;
      }
      if(turn == 2)
      {
       Mon.MonAtk();
       health.ShowHealth();
       turn = 1;
      }
    } 
    
    if(Ahealth || Mhealth == 0)
     {
      cout<<"Game Over"<<endl;
     }           
    
    
    system("PAUSE");
    return EXIT_SUCCESS;
}




^Sets the stats and starts the game loop^ I get tons of errors and don't know why if you would test it and tell me what I'm doing wrong I'd appreciate it! [Edited by - rpgman15 on May 16, 2005 12:22:45 PM]

Share this post


Link to post
Share on other sites
First thing that pops to mind is to include "beings.h" instead of "beings.cpp", but I'm not sure if that would make a difference. Just looks odd to me. Second thing, I wouldn't declare instances of the classes in the header file, but in the main cpp file.

That's all I can think of right off the bat.

*EDIT* Oh, and you're using printf like cout in one spot.

Share this post


Link to post
Share on other sites
Yeah don't include the cpp file is bad, include the .h file instead...

And including the files as #include file; doesn't work that's probably the reason of most of the errors you are getting. Include the files using double quotes and no terminating semicolon (e.g #include "foosbar.h")

Share this post


Link to post
Share on other sites
in main.cpp

#include stdlib.h;
#include stdio.h;
#include iostream;

should change to

#include <stdlib.h>;
#include <stdio.h>;
#include <iostream>;


and

#include "Beings.cpp" should change to #include "Beings.h"

Share this post


Link to post
Share on other sites
Okay made those changes and got these errors

In file included from main.cpp:4:
Beings.h:46: error: return type specification for constructor invalid

main.cpp: In function `int main(int, char**)':

main.cpp:20: error: invalid use of `class ShowHealth'

main.cpp:26: error: invalid use of `class ShowHealth'

EDIT: Got rid of errors I fixed

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You are using object here, not variables, so Ahealth and Mhealth are part of their respective instances. To actually use them, you have to specify them as

Aero.Ahealth
Mon.Mhealth

Now, take a look to your ShowHealth::ShowHealth() method. It starts with 2 return statements! It also uses variables that it has no idea about. Okay, so we have to fix these two problems.

Easy part : remove the two return statements at the start. (Just think about what a return usually does and you'll see why this isn't working!)

Hard part : we have to inform the ShowHealth::ShowHealth() method about Ahealth and Mhealth. So, basically, we have to give it enough information so that the method will be able to find it. There's a couple of ways to do this, but I'll go with what is faster (IMHO). You comfortable with pointers?

So, we have to send pointers to the Aero class and to the Mon class, so that we can access Aero.Ahealth and Mon.Mhealth. We send that as parameters to the ShowHealth functions, which will look like this now

void ShowHealth::ShowHealth(Aero *Aero, Mon *Mon)
{
cout << "Aero's health = " << Aero->Ahealth << endl;
cout << "Monster's health = " << Mon->Mhealth << endl;
cout << endl;
}



I think this should work... Try it and drop us a line. :D

Share this post


Link to post
Share on other sites
Well, lets start with the header file.

Beings.hpp

#ifndef Beings_H
#define Beings_H

#include <string>

// The Aero and Mon classes are exactly the same so there is no reason for
// them to be different classes. This also solves the problem of overloading
// or using inheritance for the attack functions as we can use proper OO
// naming schemes (i.e. noun.verb())

// Because we're only using one class for all the creatures, you need to
// name it. Otherwise we won't know which creature is which. We'll do this
// using a constructor.
class Creature
{
private:
// This is the object that will hold the name of the creature, a string
std::string name;
int health;
int attack;

public:
// The two values you had here are useless, there is no reason for
// them to exist. The private values will do fine, and they will also
// encapsulate the data of the class, which means that nothing can
// change their values without going through one of your functions

// Lets prototype that constructor I was talking about. We'll pass the
// name by constant reference so it doesn't copy it and so we don't
// accidently change it.
Creature(const std::string& theName);

// For the checking health in the main function we need some way to gain
// access to the health of the monsters. We'll create a health function
// here for that purpose.
int Health();

// New prototype, the ampersand (&) signifies that you pass the
// by reference, not by value. This allows you to actually modify the
// original copy's values as opposed to the values of a local copy
// that will be deleted as soon as the function returns.
void Attack(Creature& cr);

// This function looks alright, just needs to be rephrased.
void SetStats(int newHealth, int newAttack);

// We need to add the showhealth function here, as it doesn't need to be
// in its own class.
void ShowHealth();

// We also need a new function to subtract health from a monster because
// of the way our data is held and because of our new attack function.
void Damage(int damage);
}; // You shouldn't instantiate objects in header files.

// ShowHealth should be a function within the classes, not its own class.
#endif



Okay. Now that that is taken care of, we can move on to the source file.

Being.cpp

// The only header you need, aside from the class header.
#include <iostream>
#include "Beings.hpp"

// You can use the using namespace std; in source files (.c or .cpp) but
// if you use them in header files then you will flood the global namespace
// with all the stuff from the standard library. Bad plan. Only put this in
// source files.

using namespace std;

// We're going to use an initialization list to configure the creature.
// This will automagically set the name when the object is created as well
// as initialize the attack and health to zero.
Creature::Creature(const string& theName)
: name(theName), health(0), attack(0)
{
}

void Creature::Damage(int damage)
{
// Check to see if the damage would lower the health below zero. If it
// would, then set it to zero. We don't want negative health.
if((health - damage) < 0)
health = 0;
else
health = health - damage;
}

int Creature::Health()
{
return health;
}

// This is the new attack function.
void Creature::Attack(Creature& cr)
{
// Make the other creature take damage equal to our attack, like so:
cr.Damage(attack);
cout << name << " attacks and does " << attack << " damage!" << endl;
}

void Creature::SetStats(int newHealth, int newAttack)
{
// Simple, just setting numbers.
health = newHealth;
attack = newAttack;
}

void Creature::ShowHealth()
{
cout << name << "'s health: " << health << endl;
}


I think that's about it, now moving on to the main file.

main.cpp

// This is the proper way to include the old standard library. Using
// stdlib.h is depreciated, which means you shouldn't do it any more.
#include <cstdlib>
#include <iostream>
#include "Beings.hpp"

using namespace std;

int main(int argc, char *argv[])
{
// This is an odd way to do it, but I guess it works.
int turn = 1;

// Lets create the creatures:
Creature Aero("Aero");
Creature Mon("Monster");

// Your old functions will still work here.
Aero.SetStats(30,5);
Mon.SetStats(20,3);

// This statement was all wrong. You want to go until one or the other
// has zero health. You had the correct &&, but you cannot paraphrase
// the logic, you have to have > 0 for both of them. With your old
// system you also would have had instances where the health was lower
// than zero because you simply subtracted it. Even though we set the
// health to zero it would still be a good idea to make sure that if it
// somehow gets below zero we check for that as well.
while(Aero.Health() > 0 && Mon.Health() > 0)
{
if(turn == 1)
{
Aero.Attack(Mon);
Aero.ShowHealth();
Mon.ShowHealth();
turn = 2;
}
if(turn == 2)
{
Mon.Attack(Aero);
Aero.ShowHealth();
Mon.ShowHealth();
turn = 1;
}
}
// The logic issues here are the same as above, but the thing is that no
// matter what when you get here the health will be equal to or lower
// than zero for one of them. I'm just going to remove the logic and
// go straight to the game over thing.
cout<<"Game Over"<<endl;

system("PAUSE");
return EXIT_SUCCESS;
}



Anyway, that should be good. I did all this in notepad so if there are errors I'm sorry. You're gonna have to get someone else to point them out, or try to compile it yourself.

Edit: I decided that I had better fix it so there's no issues. The code works fine now, as far as MSVC 7 goes.

[Edited by - Bincho on May 16, 2005 1:25:36 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Bincho


Listen to this guy.

Your problems seem to be largely conceptual. A class isn't merely a place to put code; it is a template for object instances. Each object has that functionality bound to it, which logically represents things the object "can do". And the code has access to the object's variables, which have a separate existence for each object.

Anyway, basic rules of C++ still hold, and you should learn to read your compiler error messages. In particular, you should be able to understand for yourself what's wrong (technically; conceptually, what's wrong is "this shouldn't be a class", as Bincho pointed out) here:


void ShowHealth::ShowHealth()
{
return Ahealth; // <-- you can't return anything from a void function,
// and a return at the beginning of the function would
// skip everything else anyway.
return Mhealth; // And you certainly can't return twice in a row
// (unconditionally) and expect both returns to be
// meaningful.
cout<<"Aero Health: "<<Ahealth<<endl;
cout<<"Mon Health: "<<Mhealth<<endl;
// And where exactly are Ahealth and Mhealth going to come from? They
// aren't members of the ShowHealth objects, and even then, they haven't
// been set yet - this is the object's constructor after all.
cout<<endl;
};

Share this post


Link to post
Share on other sites
Thanks Bincho it work how I wanted it!

I'm going to try something similar and try and use your method.

Edit: Thanks Zahlman! You made it a bit more clearer.

Share this post


Link to post
Share on other sites
Need Help again. This time I'm adding a Item class so Aero can use the Potion item while in battle. As always things don't seem to go right with me and so I need help. I'll list my source so you guys can try and compile it and see if you can help me.

Beings.h



#include <string>


class Items //Class to hold info about the Item Engine
{
private:

std::string name;
int aohr;
int aompr;
int qnty;

public:

void Use(Creature *Aero);
int Aohr() { return aohr; };
int Aompr() { return aompr; };
int Qnty() { return qnty; };
void SetStats(int newQnty, int newAohr, int newAompr) {qnty = newQnty; aohr = newAohr; aompr = newAompr;};
Items(const std::string& theItem);
};

class Creature //Class to hold the creature's hp,mp, and attack methods
{
private:
// This is the object that will hold the name of the creature, a string
std::string name;
int health;
int attack;

public:


// Lets prototype that constructor I was talking about. We'll pass the
// name by constant reference so it doesn't copy it and so we don't
// accidently change it.
Creature(const std::string& theName);

// For the checking health in the main function we need some way to gain
// access to the health of the monsters. We'll create a health function
// here for that purpose.
int Health();

// New prototype, the ampersand (&) signifies that you pass the
// by reference, not by value. This allows you to actually modify the
// original copy's values as opposed to the values of a local copy
// that will be deleted as soon as the function returns.
void Attack(Creature& cr);

void DisplayItems(Items *item);

// This function looks alright, just needs to be rephrased.
void SetStats(int newHealth, int newAttack);

// We need to add the showhealth function here, as it doesn't need to be
// in its own class.
void ShowHealth();

void QueryInput(int x,Creature& cr,Creature& cr1);

// We also need a new function to subtract health from a monster because
// of the way our data is held and because of our new attack function.
void Damage(int damage);
};







Beings.cpp


#include <iostream>
#include "Beings.h"


Items items("Potion"); //For some reason I have to declare it here or I'll get errors


using namespace std;

Items::Items(const string& theItem) //List to initialise health restored,mp restored,and quanity of items)
: name(theItem), aohr(0), aompr(0), qnty(0)
{
}


void Items::Use(Creature *Aero) //Method to use the item
{
while(Qnty() > 0)
{
cout<<name<<"("<<Qnty()<<")\n"<<endl;
cout<<"Item Used! 10+ Hp \n";
Aero.Health() = Aero.Health() + 10;
qnty = qnty - 1;
cout<<name<<"("<<Qnty()<<")\n"<<endl;
}

cout<<"No Items left\n";
}
//Same as above but initing the name,health and attack of creatures

Creature::Creature(const string& theName)
: name(theName), health(0), attack(0)
{
}

void Creature::Damage(int damage)
{
// Check to see if the damage would lower the health below zero. If it
// would, then set it to zero. We don't want negative health.
if((health - damage) < 0)
health = 0;
else
health = health - damage;
}

void Creature::UseItems(Items *items) //Method to to use the item method in the Item Class
{
items->Use(&Aero);
}

void Creature::QueryInput(int x,Creature& cr,Creature& cr1)
{

bool attacked = false;

while(attacked != true)
{


cout<<"**********************************\n";
cout<<"* *\n";
cout<<"* What do you want to do? *\n";
cout<<"* *\n";
cout<<"**********************************\n";
cout<<"* * * *\n";
cout<<"* 1 = Atk * 2 = item * 3 = run *\n";
cout<<"**********************************\n";


cin>>x;
cout<<"\n";

switch(x)
{
case 1:
cr.Attack(cr1);

attacked = true;


break;




case 2:

DisplayItems(&items);


break;

case 3:


cout<<"You ran successfuly!\n";

//Couldn't find a way to exit so I just did this to crash the program

int * pInt;

*pInt = 20;

delete pInt;

delete pInt;




break;

default:
cout<<"Wrong Button!\n";


}

}

system("cls");

}

int Creature::Health()
{
return health;
}

// This is the new attack function.
void Creature::Attack(Creature& cr)
{
// Make the other creature take damage equal to our attack, like so:
cr.Damage(attack);
cout << name << " attacks and does " << attack << " damage!" << endl;
cout << endl;
}

void Creature::SetStats(int newHealth, int newAttack)
{
// Simple, just setting numbers.
health = newHealth;
attack = newAttack;
}

void Creature::ShowHealth()
{

cout << name << "'s health: " << health << endl;
cout << endl;

}




main.cpp

// This is the proper way to include the old standard library. Using
// stdlib.h is depreciated, which means you shouldn't do it any more.
#include <cstdlib>
#include <iostream>
#include "Beings.h"

using namespace std;

int main(int argc, char *argv[])
{

int turn = 1;

// Lets create the creatures:
Creature Aero("Aero");
Creature Mon("Monster");
Items items("Potion");



items.SetStats(3,10,0);
Aero.SetStats(30,5);
Mon.SetStats(20,3);


while(Aero.Health() > 0 && Mon.Health() > 0)
{
if(turn == 1)
{
Aero.QueryInput(0,Aero,Mon);
Aero.ShowHealth();
turn = 2;
}
if(turn == 2)
{
Mon.Attack(Aero);
turn = 1;
}
}

if(Aero.Health() <= 0)

cout<<"Aero Died!!!\n"<<endl;

if(Mon.Health() <= 0)

cout<<"Monster Dies ^_^ !\n"<<endl;

system("PAUSE");
return EXIT_SUCCESS;
}




All help is appreciated!


Share this post


Link to post
Share on other sites

This topic is 4589 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this