Archived

This topic is now archived and is closed to further replies.

Creating Better Classes

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

Recommended Posts

Okies... I have just been reading a book on C++, and I decided to write my next game using classes, etc. But the author has (kindly) left out how to actually make useful classes! Heres what I mean: Say I have a class class weapon { public: int damage; char name[20]; virtual int fire(); } and I want to make an automatic weapon subclass class automatic : public weapon { public: int clip_size; int fire_rate; int fire(); } This all works fine, but now I want to do the USEFUL stuff that classes can offer: weapon *pWeapon; //this can now be any weapon pWeapon = new automatic; //i want an automatic pWeapon->fire_rate = 20; //ERROR It now says "fire_rate is not a member of class weapon". I know that this is true, but how do I tell the compiler that an automatic is a type of weapon????? In the ideal result, i can loop through all the weapons, and do: Weapons[loop_index].shoot() and then it will call the right function - simple polymorphism. But how do I add extra information to a subclass?? It''s no use creating a weapon class that has every possible variable, to accomodate everything from grenades to laser beams! Any help would be appreciated!!! wseGuy

Share on other sites
I think you''ve got the object/class idea down. The problem is more the method of instantiation. If you have a list of weapons and you want to add an automatic, it''s more useful to define a class for your list with a member that''s insert weapon. Then create an automatic class, and pass the pointer to the class to your list. Do your iteration through the list there.

So it would look more like:
automatic * a = new automatic();
a->fire_rate = 20;
list->Insert(a);
list->ShootAll();

Share on other sites
What I would do is put fire_rate in the weapon class, and have a (possibly virtual) Set_FireRate(int firerate) function in there too. If it''s virtual, you just overload it to do the correct thing in the Automatic class.

I like food.

Share on other sites
For something like a fire rate, you would want it initialized in a generic Initialization method (i.e. override for each sub class) this will allow you to just do something like this

weapon *pWeapon;

pWeapon->Initialize();

Then you could easily accomplish something such as
pWeapon->Shoot();

This same idea will work for monsters, players, objects, etc. BTW, if you are using an inventory based system, you may be better off creating an abstract Item Class and subclassing weapons from this along with powerups, etc.

Share on other sites
Okay, maybe my post was too long (okay it Was too long) but the main point can be applied to anything.

What i want is this:

I can define an array of pointers at startup, for instance the enemies:

entity *all_enemies[MAX_LEVEL_ENEMIES];
//(not sure the syntax was right there)

then I can put in different types of enemies in there, and not have to know what they are before hand. So i don''t have to do this

big_enemy *big_enemies[MAX_POSSIBLE_BIG_ENEMIES];
small_enemy *small_enemies[....];
yellow_enemy *yellow_enemies[...];

etc.

wiseGuy

Share on other sites
so you''ve got your all_enemies array. if you wanted to create 10 big_enemies 10 little_enemies and 10 yellow_enemies. All you would have to do is:

int i, p = 0;for (i = 0; i < 10; i++, p++) {  big_enemy * ptr = new big_enemy();  ptr->height = 4000;  all_enemies[p] = ptr;}for (i = 0; i < 10; i++, p++) {  small_enemy * ptr = new small_enemy();  ptr->toe_size = 4;  all_enemies[p] = ptr;}for (i = 0; i < 10; i++, p++) {  yellow_enemy * ptr = new yellow_enemy();  ptr->yellowness = i;  all_enemies[p] = ptr;}

Share on other sites
Ah, Etnu, you have it in one! This is what I am trying to accomplish - an abstract item class that others can "evolve" from.

The problem with a virtual Initialise function is that say I want to init a grenade

but then I want to init a rifle

rifle.init(int scope_size, int shot size)

How do I accomplish this, the difference in prototypes?

Another problem I can forsee is that what if I want to change a variable midway through the program, i will still get errors.

Could I get around this by just having virtual Shoot, Reload, Get_Ammo, etc?

And then what if I want a generic OBJECT class in order to create an inventory system? My health powerups don''t a Shoot() function. What should I do?

wiseGuy

Share on other sites
quote:
Original post by wise_Guy
What i want is this:

I can define an array of pointers at startup, for instance the enemies:

You can do that. The problem you mentioned above is due to the fact that to access derived class stuff with a base class pointer requires the thing to be declared in the base as virtual and defined in the derived class. Which you can''t do with data. Thus, your pWeapon->fire_rate won''t work because fire_rate isn''t virtually defined in the base (nor can it be, for virtual can only be for functions).

Etnu''s solution is what I think you want. In the base, declare a:

virtual void setup(int, int) = 0;

and in the derived delare:

void setup(int clip, int fire) { clip_size = clip; fire_rate = fire; }

Then, in your main code you can do stuff like this:

weapon *pWeapon; //this can now be any weapon
pWeapon = new automatic; //i want an automatic
pWeapon->setup(60, 20); // sets automatic''s clip_size and fire_rate
pWeapon->fire(); // calls automatic::fire()

aig

Share on other sites
quote:
Original post by wise_Guy
The problem with a virtual Initialise function is that say I want to init a grenade

but then I want to init a rifle

rifle.init(int scope_size, int shot size)

How do I accomplish this, the difference in prototypes?

Just setup a bunch of default parameters, and know before hand which parameters are useful for what kind of weapon:

virtual void setup(int def1=0, int def2=0, int def3=0, int def4=0, int def5=0);

Then for each derived type, just use the parameters you want and ignore the rest.

quote:

Another problem I can forsee is that what if I want to change a variable midway through the program, i will still get errors.

Why? just call setup() again with the new parameters.

quote:

Could I get around this by just having virtual Shoot, Reload, Get_Ammo, etc?

nope. virtual is only for functions.

quote:

And then what if I want a generic OBJECT class in order to create an inventory system? My health powerups don't a Shoot() function. What should I do?

This will never be a problem. Just declare your weapon class as "class weapon : public object {...}". Why would you call shoot() for all your objects, instead of just weapons?

aig

Edited by - An Irritable Gent on May 9, 2000 10:30:08 PM

Share on other sites
You can''t just use a pointer to a base class to use the members and functions of a derived class, that simply doesn''t work. I believe you are thinking in reverse, you are designing it as if you are going to use the new "abilities" of the later class in a pointer to the base. Instead think of how you can create general abilities that all of that type of class have and use those. Then when dealing with the derived classes use pointers to the derived class.

Some suggestions to follow:
1. Try thinking of all the abilities that the object will have (example for weapon: Fire and Reload)
2. When dealing with the derived class, treat it as such, not the base, type casting works great in this instance.

Here is a great way to think of it all, you are building an interface. What it the interface of a weapon? You can fire it somehow and you need to reload it when it runs out of ammo. So in the base class give it these abilities. Then in its derived give them their unique abilities. Then if you have a function that works with weapons it can use all of them with the base functionality, to fire and reload. HOWEVER, it won''t be able to use the special abilities, you will need separate sections of code that know EXACTLY what type of derived class it is dealing with.

If I could think of some OOP books of the top of my head that taught OOP design I would tell you. Someone here probably knows. OOP takes a little getting used to, it has many great features, but is a little tricky on the first few tries.

-Omalacon

• 12
• 10
• 10
• 12
• 21