Sign in to follow this  

Classes in Headers

This topic is 4305 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

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~

Share this post


Link to post
Share on other sites
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.def
12 5 0 2 15 100

Beast.h
Beast 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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Quote:
Original post by valla2
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


If you've lost your password, how are you logged in?

Also, to the OP, you could consider making LoadBeast into a constructor for Beast.

Share this post


Link to post
Share on other sites
from the trenches (and reinforced with a ton of Java experience):

The headerfile is your public interface. Put in there that which your users will need to use the class.
That means no method bodies at all (except maybe some exceedingly short getters and setters but I'd go clean and remove those as well), only definitions.

Everything else is put in a cpp file which imports that header just like any other file that would use the class.

So your beast class would go something like

beast.h

#include <string>

class Beast {
public:
Beast();
virtual ~Beast();
std::string get_name() const ;
void set_name(const std::string& the_name);

private:
std::string name;
};




beast.cpp

#include <string>

#include "beast.h"

Beast::Beast() {
name = "";
}

Beast::~Beast() {
}

std::string Beast::get_name() const {
return name;
}

void Beast::set_name(const std::string& the_name) {
name = the_name;
}




As to multiple classes in a single file, nothing wrong with that as long as they're closely related.
So a beast and some basic derivatives (like a generic bird and fish) I'd probably put together, but not a beast and a castle.

Share this post


Link to post
Share on other sites

This topic is 4305 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