Jump to content
  • Advertisement

Archived

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

Kars

Multiple Inheritance. Good or bad

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

specifically in C++. I was planning on doing something like having three classes and depending on what I wanted, inheritance from them. i.e. Base classes 1) VObject - draw an object. 2) SObject - used to make an object "sold" (collision detection) 3) Movement - used to handle moving objects. So if I wanted an invisible wall that moved around the board I would inheritance from SObject and Movement. If I wanted a bird flying in the sky that was just eye candy (can''t be hit, etc) inheritance from VObject and Movement. etc.... This seem like a good Idea? or is there a better way to handle this? Any performance penaltys attached to Multiple Inheritance? Harder to debug? Do most compilers handle it the same way?

Share this post


Link to post
Share on other sites
Advertisement
I wouldn''t use MI for that. I''d just use a single base class, and use interfaces for all the functionality you need.

Share this post


Link to post
Share on other sites
I do something similar, but using the technique that daerid suggests, which are abstract interfaces.

Also, i call mine ICollidable, IRenderable, IMovable.

Good luck

Share this post


Link to post
Share on other sites
Rember what public inheritance is. It exprepresses an "is-a" relation. "Is" a bird a movement? Obviously not. It''s a bit harder with VObject and SObject. Well, you could say: a bird *is* a visual object (that''s what I intend the V at VObject to be ment for) and it *is* a solid object. But what you really try to add to your object is a special behavior. It is "drawable" "collidable" "movable". That''s why you would better stick to interfaces (like jonnii and daerid told you already) as they express a supported behavior. Only use inheritance if you want to *specialize* a given class. Example: class Woman inherits from clas HumanBeing. A woman (in deed) *is* a HumanBeing, but with specialized properties (which we all know soooo well - sorry girls *g*).

Hope that helps to explain why MI is not a proper usage in this case.

In fact, MI is (almost) never neccessary. Guess why Java, .NET etc. got rid of it?

Regards,
VizOne

Share this post


Link to post
Share on other sites
quote:
Original post by VizOne
Guess why Java, .NET etc. got rid of it?

Mostly because it is really hard(and costly) to implement correctly.
Incidentally, Eiffel.NET DOES support MI. It had to, since the standard Eiffel libraries rely so much on MI(Any Eiffelite will tell you that MI in C++ is totally braindamaged, while Eiffel got it right).

--
AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.
[Project site] [Blog] [RSS] [Browse the source] [IRC channel]

Share this post


Link to post
Share on other sites
Ah, more thoughtless MI-bashing.

quote:
Original post by VizOne
Rember what public inheritance is. It exprepresses an "is-a" relation. "Is" a bird a movement? Obviously not.


That''s just semantics, really. Suppose Movement was called MovableObject: a bird "is" a MovableObject.

The point of inheritence, multiple or otherwise, is firstly to arrange a heirarchy of kinds -- a bird is a kind of solid object, a kind of visual object, and a kind of movable object -- and secondly to allow classes to reuse code from other classes.

Here, it is likely that the solid object class contains much that is relevant to collision detection. This includes methods for checking for collision, and therefore information about the shape of the bird.

The visual object class contains members relevant to rendering objects. This includes methods for actually rendering the object, and therefore information about the appearance of the bird.

The movable object class contains members relevant to object movement. Methods for applying physics to the object is likely to be here. There is some overlap between solid objects and movable objects, since physics may go as far as collision response between the bird and the rest of the world. This may imply that the movable object class is bogus.

Clearly, a bird will need to use the features of all of these classes. With inheritance from virtual classes for Drawable, Movable and Collidable, all the code for drawing, moving and colliding the bird must be replicated in the bird. This runs contrary to the principle of code reuse. You end you having to write the same code repeatedly, which suggests this particular design is bogus.

C++ still has issues, though. Observe that the visual and solid object classes both need information about the geometry and appearance of the bird. In C++, each class holds that information seperately, and therefore memory is wasted. As Arild points out, Effiel is better -- in this particular situation you could set things up quite easily so that only one copy of the bird''s model is kept.

Share this post


Link to post
Share on other sites
To throw my two cents in, I recently worked on a project with a considerably deep class heirarchy for all objects in the game, done to provide this kind of system. The class heirarchy, starting from the top at ''Player'' went like this:

Player->Human->Biped->PhysicsBiped->DrawableBiped->DrawableObject->Object.

Unfortunately, at some point we wanted Human objects that had no physics within them - they were animating NPCs without any need for collision detection.

Because of our heirarchy it was impossible to remove the physics code, and more importantly the variables & state information, from the Human. The sollution involved putting the state information for PhysicsBipeds into a structure that could be dynamically allocated, effectively allowing us to remove the PhysicsBiped from the heirarchy. This is a horrible sollution, but worked for our time frame.

In any further development I would use an aggregate container class that either held references to classes that provided the required tasks or registered itself with some kind of feature manager that let the required functionality and state variables be assigned to the object without the cumbersome class heirarchy.

What does this mean to you? Well I would be worried about implementing multiple inheritance since you pull in a lot of functionality that may at first seem reasonable, but may ultimately be unused as the design of your project changes. I don''t have an elegant sollution for you at this time; I''m still experimenting with it myself. Granted our problem with compounded by being a title targetted at multiple platforms simultaneously.

- S

Share this post


Link to post
Share on other sites
Personally, I don''t have much issue with multiple inheritance, I''m just really hard pressed to find situations that really merit it.

The following is my take on the matter and the greater issue.

This falls under to the language features debate. Which in and of itself needs to be debated and understood.

Language is what we use to express ourselves across a specific medium -- realise that a change in medium has a dramatic effect on the language or at least the message.

There are two extremes. One is an exceptionally static language, that doesn''t change and you use it to SOLELY build more vocabulary but no syntactic constructs. The other is that the language is very simple and to a significant degree redefinable such that one can not only create new vocabulary but one can also build new syntatic constructs. Now depending on the language''s and the programmer''s philosophy, they''ll take varied approachs to solving a problem.

If we take Java as an example, the language is very static, "good" programming practices are enforced everywhere. The idea of multiple inheritance is taken away and interfaces are brought in if one is looking for multiple-inheritance -- you''ll just find it in a diluted form.

You simply have to decide where you wish to fall within the aforementioned spectrum. Once you know that, you''ll have an idea what the truth is and will act accordingly. If you have the facilities to fall on one side of the debate and figure out what is "good" then you''ll know if multiple inheritance is "good", just remember, that it maybe easy for you to deal with multiple inheritance but will it be for those maintaining your code -- this of course could be you.

Share this post


Link to post
Share on other sites
Good, but much like a chainsaw or blowtorch, shouldn''t be placed in unexperienced hands. It''s very easy to maim your program with poor multiple inheritance use, but not having the feature when you need it would suck.

In your case, don''t use MI. Why?

VObject, SObject, Movement, Health, Armor, who knows how far you may want to extend an object''s capabilities. The result is:


class CKnight : public VObject, SObject, Movement, Health, Armor


Not only is that ugly and slow to compile, but good luck not accidentally colliding member names and trying to keep track of what''s going on. Do it the interface way like others said.


CustomBar

Share this post


Link to post
Share on other sites
quote:
Sphet
Player->Human->Biped->PhysicsBiped->DrawableBiped->DrawableObject->Object



This also means that players could only be humans. Surely an obvious solution would have been to add a Boolean toggle to PhysicsBiped that indicates whether or not physics should be applied?

quote:
Original post by LordElectro
Good, but much like a chainsaw or blowtorch, shouldn't be placed in unexperienced hands. It's very easy to maim your program with poor multiple inheritance use, but not having the feature when you need it would suck.

In your case, don't use MI. Why?

VObject, SObject, Movement, Health, Armor, who knows how far you may want to extend an object's capabilities. The result is:


class CKnight : public VObject, SObject, Movement, Health, Armor


Not only is that ugly and slow to compile, but good luck not accidentally colliding member names and trying to keep track of what's going on. Do it the interface way like others said.


Seeing as the above line would be the same with interfaces, and that member names of interfaces can collide, I don't see how interfaces are going to solve these problems.

Sure, interfaces make it easier to see what's going on: because you write all the code yourself. You can apply the same rule to single inheritence and conclude that you should never inherit implementation, no matter what, because you might not know what's going on in the class.

If the classes you inherit from are well designed and documented, you will always know what a particular superclass is going to do in a particular situation.

EDIT: Darned quote tags.

[edited by - Mayrel on October 22, 2003 6:49:38 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!