Classes in Headers

Started by
10 comments, last by jwenting 18 years, 2 months ago
I have heard that I should be creating all my classes in my '.h' files in my project. I have some 100 classes with one type class(well, I WILL have a hundred later; now I only have four) I have my '.beast' class with four monsters to go in it(or play off of it?); Is it bad code to have all my (soon to be) hundreds of monsters in the header or is that even how I am supposed to do it? Right not I have only my class type (beast) in the '.h' file and the rest in a source(?) file. Also, I would try it out myself, but my program isn't complete yet; I could create a smaller project or try and fix my program as to run right now, but it is much simpler to pop the question it here and hope someone knows the answer without checking or wasting their time. If not, I will simply figure it out later. Thanks. ~S of the L~
Advertisement
The best way to do this would be to make it data driven. Create a way to load a monster (or beast as it's called in your engine) from a file (text or binary, text is more work, binary is less editable). Then you can change properties of monsters without recompiling. In fact, the best way to do it would be to create a simple archive file that stored all of the monsters called Creatures.bin or something, that could store each monster with a unique ID. Since it's binary, your average user would have trouble hacking it without a hex editor, or the editor that you use. If the idea of creating a binary archive format sounds daunting, then I'd just create individual files with the names of the monsters where each property is whitespace separated, like this:
Goblin.def12 5 0 2 15 100Beast.hBeast LoadBeast(const char* beastname){  std::istream beastfile(beastname);  Beast dummy; //using auto variables is not the best way to do this,  //a better way would be to pass in a reference of a Beast and use that.  //Then it would likely return an error code instead of a completed beast.  beastfile >> dummy.hp;  beastfile >> dummy.mp;  beastfile >> dummy.armor;  beastfile >> dummy.attack;  beastfile >> dummy.gold;  beastfile >> dummy.xp;  return beastfile;}


You'd have to error check, and your monsters probably have more attributes, but it's a start.

[Edited by - Drakkcon on March 2, 2006 10:28:07 PM]
Quote:Original post by Servant of the Lord
I have heard that I should be creating all my classes in my '.h' files in my project. I have some 100 classes with one type class(well, I WILL have a hundred later; now I only have four) I have my '.beast' class with four monsters to go in it(or play off of it?) ...

It seems like there is a little confusion about what a class is. In this code, Beast is a class:
    class Beast    {        ...    }; 
The code above generally goes in a header file. Classes generally go in header files so that code in other files can use them. Functions and data usually go in source (.cpp) files.

In the code below, goblin, elf, orc are instances (or objects) of the class Beast. Sometimes, people will refer to an instance as a "class", but they assume you understand they are really talking about an instance and not the class itself.
    Beast goblin;    Beast elf;    Beast orc; 

Now, some people when they learn about inheritance, they go crazy. They might create a different class for every type of object, like this:
    class Goblin : public Beast { ... };    class Elf : public Beast { ... };    class Orc : public Beast { ... };    ... 
Usually, that is not a good idea because the behavior of the classes are the same, and the only difference is the data they contain. You are adding complexity where it is not needed. So, better is to keep the various types of creatures as Beasts, but with different values. That is what Drakkcon is talking about. On the other hand, you might create a FlyingBeast subclass and a WalkingBeast subclass because their behaviors are different.

Read this if you haven't already: Organizing Code Files in C and C++.

Hope this helps.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Yes, sorry. I thought he meant creating a base "Beast" class and inheriting from it for each beast. JohnBolton is correct, you will want to create one Beast class and instance it for each kind of monster (though loading that monster's attributes from a file would certainly make things easier).
Thanks Guys! That helps alot. To clarify though: (read notes in code please)

Goblin.def//Am I correct in thinking this is the file your loading from? 12 5 0 2 15 100  //If so, why '.def'? (what does it stand for, also; define?)                  //Why not a .txt unless for security?Beast.h   //What am I to put in 'Beast.cpp'?Beast LoadBeast(const char* beastname){  std::istream beastfile(beastname);//So if I tell this to load 'Goblin'                                    //it would load Goblin.def and go like                                    //dummy.hp = 12;dummy.mp = 5; etc...                                    //And then overwrite it with Hobgoblin.def                                    //when I load that?  Beast dummy; //using auto variables is not the best way to do this,  //a better way would be to pass in a reference of a Beast and use that.  //Then it would likely return an error code instead of a completed beast.  beastfile >> dummy.hp;  beastfile >> dummy.mp;  beastfile >> dummy.armor;  beastfile >> dummy.attack;  beastfile >> dummy.gold;  beastfile >> dummy.xp;  return beastfile;}


And would/should I organize my beast files in a different folder(inside my prog folder)? If so; I am not familiar with how to load a file from any other folder than that which has the prog that loads it. How could I? (I realized I never mentioned I used Dev C++ or even that my laugage was C++; hope you haven't been wasting your time teaching me C# or Java or something I don't use(yet). Once again: Thank you.

Quote:Original post by JohnBolton
It seems like there is a little confusion about what a class is. In this code, Beast is a class:
class Beast
{
...
};

I know what it is, I just forget the term for instances so I call the above class types and the below classes, hoping others will understand. I really should try and get the standard terms right.
Quote:The code above generally goes in a header file. Classes generally go in header files so that code in other files can use them. Functions and data usually go in source (.cpp) files.

In the code below, goblin, elf, orc are instances (or objects) of the class Beast. Sometimes, people will refer to an instance as a "class", but they assume you understand they are really talking about an instance and not the class itself.
Beast goblin;
Beast elf;
Beast orc;

Now, some people when they learn about inheritance, they go crazy. They might create a different class for every type of object, like this:
class Goblin : public Beast { ... };
class Elf : public Beast { ... };
class Orc : public Beast { ... };
...
Usually, that is not a good idea because the behavior of the classes are the same, and the only difference is the data they contain. You are adding complexity where it is not needed. So, better is to keep the various types of creatures as Beasts, but with different values. That is what Drakkcon is talking about. On the other hand, you might create a FlyingBeast subclass and a WalkingBeast subclass because their behaviors are different.

Thanks, I'll make a note of that.

Quote:Read this if you haven't already: Organizing Code Files in C and C++.

I've read it awhile ago,(a week or two) But I will look through it again(just bookmarked it as well) Thanks.
Quote:Hope this helps.

Greatly, thanks many times over. Programming is all new to me,(only been coding for whatever my 'joined' is plus a day or two. Somewhere about seven-eight months,) and I need things repeated all the time because I am trying to learn more complicated things than I normally do in less time.(and the fact that I don't like complicated math doesn't help. [smile]) I greatly apreciate what this site and(more importantly) the users have done for me. I would be nowhere and never get anywhere had it not been for this site's users. Thank you.

[Edited by - Servant of the Lord on March 3, 2006 12:24:26 AM]
Quote:

Goblin.def//Am I correct in thinking this is the file your loading from?
12 5 0 2 15 100 //If so, why '.def'? (what does it stand for, also; define?)
//Why not a .txt unless for security?


You are correct, this is the file we're loading from. I believe in giving all of your files meaningful extentions, and you are correct in that it stands for define. The reason I didn't call it a .txt is so that the default icon for it wouldn't be a notepad (and many average Joes wouldn't even try to open it). It's not secure, you can just use the select program menu under windows to open it.

Quote:
Beast.h //What am I to put in 'Beast.cpp'?


The actual function declaration:
Beast LoadBeast(const char* beastname);

should go in Beast.h. The definition (that's what I showed you) should go in Beast.cpp. As you probably learned from the organizing code tutorial, you should also use inclusion guards and have Beast.cpp including Beast.h.

Quote:
Beast LoadBeast(const char* beastname)

{
std::istream beastfile(beastname);//So if I tell this to load 'Goblin'
//it would load Goblin.def and go like
//dummy.hp = 12;dummy.mp = 5; etc...
//And then overwrite it with Hobgoblin.def
//when I load that?


Not quite. Notice that this function returns a Beast. This is how you would use it:
Beast hobgoblin = LoadBeast("hobgoblin.def");Beast evilMotorcycle = LoadBeast("evilMotorcycle.def");Beast brigand = LoadBeast("brigand.def");

We create a beast in the function, and then return it to hobgoblin.

This is the simplest way of doing this. A better way would be to pass a beast in by reference like this:
void LoadBeast(const char* beastdef, Beast& beast){  std::istream file(beastdef);  file >> beast.hp;  //and so on}


used like this:
Beast dragon;LoadBeast("dragon.def", dragon);//the data gets loaded into dragon.


This way we don't actually have to create a new beast in the function, so it's faster and uses less memory.
Thank you, I think I get it. One last question on a slightly different topic; how do I load files from a different folder than my program is in? I can load files(somewhat) but only when they are in the same folder as that which I am loading from.
Just use the full path, like: "c:\whatever\foo.txt" or use a relative path, like "..\foo.txt".
Thanks Drakkon; I was confused about my test program for a second. It pulled up the errors: unknown exit command \T,\M,\W;[\b] but I figured out it was just my path reading wrongly and double side slashed it: \\ Thanks for all your help.
hi
i want to make a priority queue keyed on a value. The priority_queue<> in the STL is ok for me, but it doesn't let me change that value for an element and automatically change its position in the queue ( it would be great if there was a function CHANGE_KEY_VALUE() ). How could i do this, in C++ (using STL if possible)?

btw i couldn't make a new thread because i lost my password.. can a moderator move this post to a new thread?

thanks in advance

This topic is closed to new replies.

Advertisement