Home > OS >  How to avoid dynamic_cast in this case?
How to avoid dynamic_cast in this case?

Time:04-19

I have 3 classes in my program:

class GameObject{

    private:
        std::pair<int, int> position;
}

class World{

    private:
        std::vector<GameObject*> gameObjects;
        int gravity;

}

class MovingObject : public GameObject{

    private:
        int velocity;
        bool isSensitiveToGravity;
        unsigned mass;
}

I am using a vector of GameObject* in the World class because I want to put in there every object that is in the game, and some objects are not MovingObject instances.

But I see a problem there: during the game, I will need to loop on world.gameObjects in order to check if an object is sensitive to gravity to drag it down if it is the case, but how should I do this?

My first idea was to add a pure virtual method in the GameObject class that would be implemented in the MovingObject class and return whether an object is sensitive to gravity or not, but isn't this a weird design?

The other idea is of course to use dynamic_cast on every object, check for (sub)class of MovingObject, and then check for the isSensitiveToGravity field, but I read a lot that dynamic_cast should be avoided and is almost always a sign of bad design, so where is my error here?

Thank you!

CodePudding user response:

When you think in terms of functionality in OOP you should think in terms of interfaces and not structs of data. This is exactly the case so you should create an interface with a function interactWithGravity and use it. In case this is an object that does not interact with gravity simply do nothing.

To emphasize why this it the correct solution let's consider the other alternative, having a parameter determining if it's moveable by gravity or not. This has the following cons:

  1. If you'll have more parameters the affects how certain objects are interact with gravity means adding another property to the common struct (although it's only relevant to some).
  2. The previous example also suggests you'll need to expend you're cases in the main function that goes over the objects and make the code more complex and harder to expend.
  3. Perhapse you'll find it easier to do the "gravity calculations" in polar coordinates. This means changing all the calculation and coordinates in the different objects.

Holding different lists may be reasonable if you need to do some optimizations but otherwise it will be less reusable and expendable from similar reasons.

The list goes on and on with other concepts like ISP but you get the general idea.

  • Related