Reputation: 73
Is the only point in implementing the 2nd case is if I want to derive from a Collidable without being an Object? If that's the case, when is the 1st case ever favorable since the 2nd case offers more flexibility.
Both collidables have only a pure virtual function and Object is a base class for objects that can be drawn on the screen (in my case).
^Assuming I'm understanding the following code correctly (I'm not too sure TBH)
class Object
class CollidableObject : Object
class Actor : public CollidableObject
class Object
class Collidable
class Actor : public Object, public Collidable
Edit:
Based on Matt/Seth
class Object
class Collidable
class Clickable
class Trackable
class BlowUppable
class Actor : public Object, public Collidable, public Clickable, public Trackable,
public BlowUppable
class SomeObjectThatIsTakenForGrantedThatEverythingElseIsInherited : public Actor
First example is the second case and second example is the first case. I guess thats the only use I see for the first case.
@Luchian
This is going to be a different question from the original since your reply was neither.
In this case, is there a difference changing an object from a is-a to a has-a relationship? In each case, to check for collisions, an object has to has to have a flag to know if collision should be checked. In your case, the member can be checked if its null or not, but in the derived case, the object itself tells whether it can collide or not. In an array/tree, I can either pass the derived object as a argument or pass hitbox as an argument using a get() method.
To be more in depth, I have another class - using the second case
class Hitbox : public Object, public Collidable
and the Actor class has it as a member
class Actor : public Object
{
Hitbox *box;
};
Objects that have collision would have a hitbox instead and this represents your post accurately I think. But what's still getting me is that when I review your example again, does it mean that Hitbox should have a Collidable member instead?
class Hitbox
{
Collidable *collision;
};
What I have:
An Actor holds a Hitbox which handles collision
What Hitbox should do:
Inherit Collidable or
Have Collidable as a member
Actor is already following your convention. Should Hitbox do the same?
Upvotes: 7
Views: 261
Reputation: 4905
Is the only point in implementing the 2nd case is if I want to derive from a Collidable without being an Object?
Yes, the second case gives you more flexibility as it allows to separate the interfaces. For example, later you may want an object that is collidable but it is not drawable.
When is the 1st case ever favorable since the 2nd case offers more flexibility.
The second case offers more flexibility but it is also more complex to design. At the end, you will need virtual inheritance and this is more difficult to handle. However, if your base classes are pure abstract it should not be a problem.
You may see this.
Upvotes: 0
Reputation: 258618
This is a perfect scenario for the strategy pattern. This is where the English language plays tricks on our minds and makes us think that CollidableObject
is a valid object to have in this hierarchy. I say collision is more of a behavior than an object, so I'd go with neither of the two.
Prefer composition for this:
class Object
{
CollidableBehavior* collisionBehavior;
}
class Actor : Object
{
// collisionBehavior = new ActorCollision()
}
class AClassThatDoesntCollide
{
// collisionBehavior = NULL
}
Upvotes: 1
Reputation: 10564
I would do the second case, as Object
and Collidable
are cross-cutting concerns. If you go the CollidableObject
route, you will probably end up with a combinatorial explosion of classes. It won't be long until you see a CollidableTrackableClickableBlowuppableObject
.
Since Collidable
is pure virtual, it is used in this case as an interface, so doesn't have many of the criticisms that argue against multiple inheritance. You are simply stating that an Actor implements the Collidable
interface.
Upvotes: 2