开发者

C++ design problem

开发者 https://www.devze.com 2022-12-16 13:33 出处:网络
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) a

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消