Inheritance Question

In my game I have a class Object which contains all members needed for objects (weight, size, etc.) I also have specialized infomation for Containers, Weapons, and Armor, which I thought would be a good idea for inheritance (Container/Weapon/Armor inherits from Object) However, the issue is that I would need to know the type at run-time (for determining whether you can look inside the object, etc.), since players can have any of the 4 object types in their inventory at once (normal objs, containers, etc.). I would like to avoid using RTTI, but I sort of doubt I could do this any other way if I was going to use inheritance. Any thoughts on just using RTTI/dynamic_cast or using some other method (like a string or an enum in the object class telling me what type it is)?
This is always a tough call to make. I don't have a definitive "best" solution, since it depends a lot on exactly how the classes are going to be used.

I'd prefer an emun to a string to identify the type, since you can throw it in a switch(). The problem with that is it's makes it so hard to expand or change your hierarchy later. What if you add a new type that has some properties of a weapon, but not all of them? You'll have to go back and check/modify all the switches in your program to reflect the change.

Another (but not all that great) idea is to give Object an abstracted interface for doing things on a lower level in the hierarchy. For example, Object could have a virutal function IsContainer(). Object::IsContainer would return false, Container::IsContainer would return true, and the other classes wouldn't need to implement it.

This makes expanding easier. Whenever you need to have a property that gets items to act differently, you can just add a new virtual function to Object (and have it return an appropriate default value) and no derived classes will be ill affected.

The downside is you might end up cluttering Object with too many virtual functions if you get carried away. If Weapons have 5 functions that apply only to weapons and nothing else, then it doesn't make much sense to put all of those functions in Object.


It might be easier to come up with a good solution if you pose a specific problem that'll be typical for your program. When would you need to fork your objects into different types? Is there any way to have the logic fork put into a more generic "Perform" virtual function so that you don't need to discern the type? (that is what would be ideal)
You could make "capacity" an object attribute. Non-containers would have a value of 0.

Why the hesitance to use RTTI?
I kind of agree with Disch, but I would do it differently.

Here, we are assuming that you start in Object, and in a single jump you end up with your final classes, so you have a max-2 hierarchy. You can probably do a "finer" hierarchy by adding more (possibly abstract) classes.

For example, Weapon and Armor can possible be used by the character. This means that you can define a new abstract class that inherits from object called, say WearableObject. Then you add pure virtual functions to WearableObject common to both Weapon and Armor, and then you make Weapon and Armor inherit from WearableObject.

Basically, I would say you need to think more about your classes before you continue coding.
While an excellent academic exercise for learning OO principles, I personally find that using object
hierarchies/inheritance to model data like this in real world programs is almost never useful.

The question I have for firedraco is: what will you gain by tightly coupling these things via inheritance?
Polymorphism: probably not, because there is little in common that chain mail has with a dagger and
with an empty flask. And furthermore, since you already acknowledge the need for RTTI, it
contraindicates putting these things into a container.

Will you gain code reuse? Again probably very little. A CalcDamage() function used by a Weapon class
would not be at all applicable to a Scroll object; a Read() function used by a Scroll object would not
at all be useful to an Armor object. It probably would be very hard to find any real common methods
to put in a base class (even if those methods had to be pure virtual). So the only code reuse you get
is perhaps a data member or two, and not even any methods that operate on them. Inheritance is
awfully expensive (from a maintenance standpoint) just to save a few keystrokes.

If neither of the above, then what is it you gain?
Wow. It is hard for me to read this, jsmith. Are you being dead serious?? Nothing in common? No polymorphism to gain? Wow.

A chain mail, dagger, and empty flask can be contained objects (in the backpack). Your collection would be of the base class of these classes, like IContainable (using interface naming here). The methods? Well, some things are larger than others, and the backpack can probably carry up to X units of storage, so IContainable would have a method like GetStorageUnits() that tells the collection how many storage units an object takes. The chain mail would require more than the dagger or the empty flask.

As for code reuse, that may become a bit harder, I agree, but the real advantage here is polymorphism, and that alone pays the bill. Still, CalcDamage() or something similar could be used by both a Weapon class and a Scroll class because the scroll may contain an attack spell.

I just can't live without polymorphism in my everyday programming. I just don't understand how anybody can. The best models are polymorphic, and the greatest example is: The .Net framework.
@webJose:

I suppose if the game allows the player to wield a scroll as a weapon, fine, otherwise there will be dynamic_cast<>
everywhere. An alternative would be to have the backpack object have several non-polymorphic containers. This
would avoid the casts.

So I have not programmed a game of this sort myself, but I have played them. As it stands now, there are two
methods/attributes that can be shared among items (though I do not see every item as inflicting damage, but
perhaps) to exchange for all of the dynamic casts.


I just can't live without polymorphism in my everyday programming. I just don't understand how anybody can. The best
models are polymorphic, and the greatest example is: The .Net framework.


Sorry, did I say I was across the board against polymorphism? In this case, yes. In general no. Polymorphism has
its benefits. I just think (with my limited window into what OP wants to do) that polymorphism is not necessarily
the "obviously right" solution.


A few reasons I can think of:

-) Randomly generated items of any type can be created with a function that returns an Object*
-) Recording what object lies at which point on the map can be recorded as a group of Object*s. For example if this is a tilebased roguelike -- each tile could have an Object* specifying the item that is on the floor at that point in the map.
-) The player's entire inventory can be a vector/array of Object*s
-) Common properties that all items have (name,weight,etc) can be in Object and thusly don't need to be repeated for each item type (which would result in a lot of if/else/switch redundant code for any code that needs to check those properties)

I think polymorphism is the right thing to do here.

Granted it's not ideal to have to downcast, but sometimes you have to do it. That's why C++ let's you.
Have you considered any type erasure technique?
I'm not familiar with the term, myself (I might know the technique, but I suck at knowing the names for things).

Can you elaborate?
I once read, in C++ Programming Style by Tom Cargill, that polymorphism was not the solution to every problem. Similarly, virtual methods should be used to change behavior not value.

Most of the information present in the thread leads me to favor a single Item class with various attributes (values).

Item, has a name, has a size, has a etc. To vary the behavior beyond that, consider the Decorator pattern. Decorators, according to Design Patterns by GoF, are a flexible alternative to subclassing.
Last edited on
Thanks for the all the input! The reasons why I was thinking of going the polymorphic route was mostly the the reasons Disch stated (all of them in fact).

After thinking about this for a bit, I sort of came up with this kind of an idea:

Just one object class, that contains all the data members for everything (for armor/weapons this actually isn't a problem, as it might be interesting to let players wield a shield or a helmet to bash people with). The only possible issue is for containers, as I would have an extra vector of Objects that would be empty for non-containers (shown my having their max_container_size == 0). But I think such overhead probably wouldn't be too bad.

It would also let me make strange objects like a shield with a compartment to store items, etc.
Type erasure allows you to treat disparate types polymorphically without the need for derivation from
a base class. This allows you, for example, to store Fruit, Vegetable, and Meat objects in an STL
container without having to derive all three from a common base class Edible (and then storing pointers
to Edibles).

The most well-known example of type erasure is boost::function.
Last edited on
About type erasure, actually that sounds quite interesting, too bad the Wikipedia article was only 3 lines...although I'm not completely sure if there is a simple way to implement it here.
That 'storage shield' could have spots to put spikes on it or other things that give the shield's inventory a completely different purpose than a container's. Weapons could be enchanted or have poisons added to them. A box could have something put into it while a sword could have something put on it using the same functional interface. What about traps?
I wonder how FF7 implemented materia sockets on items.
@jsmith: That's just a fancy term for void*. ;-)

This is the sort of problem where strongly-typed dynamic languages like Python really come through.
syneris wrote:
That 'storage shield' could have spots to put spikes on it or other things that give the shield's inventory a completely different purpose than a container's. Weapons could be enchanted or have poisons added to them. A box could have something put into it while a sword could have something put on it using the same functional interface. What about traps?


Yeah, but those would probably be more like attachments you can add to the item. What I was thinking of was more like a hollow(ish) shield that you just open up and put stuff in.

I wonder how FF7 implemented materia sockets on items.


Proabably just something like:
unsigned int num_dual_slots, num_single_slots;
And then just require it not to be > 8 slots.
I was just adding in some conceptual uses of a polymorphic solution.
As for FF7, just knowing the number of slots doesn't mean much. They had to program the ability to equip/unequip the slot, have the effect added/removed, and modify the materia stats (haven't played 7 in a few years and I don't remember the full extent of their use.) Each materia was a separate object and gained AP. There are many possible ways to handle the same situation with 'right way' usually being just an opinion.
I wonder how FF7 implemented materia sockets on items.


Having been a professional software developer for over 10 years, I think I can honestly (cynically?) say
that the grass is always greener on the other side of the fence. It is easy for me to "see" the object-
oriented-ness of other companies' products. But when I look at my own -- it isn't a whizbang state-of-the-art
(insert your favorite buzzword here) design. It, as most other large products (my cynical side would say,
in consideration of the companies [plural] that I've worked for) was designed in pieces over time by a collection
of engineers whose experience and competence levels follow that of a typical bell curve: a few are really good,
a few are outstandingly bad, most are somewhere in the middle. The overall design therefore tends toward
average, although there are pieces of the system that are architected much better or worse.

Furthermore, game programming (of which I have only second-hand stories and no experience myself) is perhaps
a different beast. The cliche, true or not, is that game programmers work a lot of hours. Furthermore, game
programming requires special characteristics: when designing some game-specific piece of software, perhaps
such as the materia mechanism on FF7 (have they used the materia mechanism unmodified in any other games?),
the focus isn't necessarily on readability or maintainability; it is rather on getting the job done and, in many cases,
on a solution that is fast.

Having said all that, I would not be the least bit surprised to see the materia mechanism implementing in a
disappointingly low-tech manner. No whiz-bang template solution or object hierarchy: perhaps just a single
struct containing the attributes of the materia and a lot of if() statements.

IMHO.
Topic archived. No new replies allowed.