I have a class hierarchy as such:
Entity
Stationary
Tree
Creature
Bear
Crow
And I have a World and a Player. When the Player bumps into something it gets a call to handleCollision(Entity* entity) and then depending on what it is different things happen; if the player bumps into a tree not开发者_开发百科hing happens while the player attack if it's a bear. The problem is that I'm not sure how to differentiate between cases in a good way.
One thought that has come to mind is someting like this. Player::handleCollision(Entity*) calls Entity->handleCollisionHelper(Player& ). This is a virtual function which in Tree does nothing and in Creature(it should attack all creatures) calls Player.handleCollisionCreature(this) and then place the attack code in handleCollisionCreature. Is there a better way to do this without using RTTI (typeid etc)?
The virtual method with (Player& player) arg seems perfectly good OO design. As you said, you could add some form of type or use RTTI and switch case through the permutations but that would be very C style functional style. Just as long as you aren't making thousands of virtual calls per second you should be fine.
Just to provide a reference for the official name - this problem is known as Double Dispatch (you need to decide what to do based on the type of two objects at the same time).
See the Wikipedia article http://en.wikipedia.org/wiki/Double_dispatch for some details, and a suggested solution.
Instead of triggering on Entity*, why don't you have something like this:
handleCollision(Stationary& stationary)
{
// Nothing to do yet?
}
and
handleCollision(Creature& creature)
{
creature.StartCombat(this);
}
And remove the Entity* function. This will ensure only creatures will start combat (Add StartComabt function to your Creature class). Alternately, you could have a Combat class:
handleCollision(Creature& creature)
{
Combat::Begin(this, creature);
}
I think what you're looking for is called "double dispatch" or "multimethods".
Calling different functions depending on the dynamic type of more than one object is not a built-in feature of C++, but there are a number of well-known techniques to roll your own. Cascaded calls as you propose is probably the most common one.
精彩评论