MeLikeyCode
MeLikeyCode

Reputation: 295

Two objects that need to reference each other. Bad Idea?

I am developing a very small and simple game engine in C++. I have a Creature class and a Weapon class. The Creature needs to know what Weapon(s) it has and each Weapon needs to know the Creature that has it. The main reason why I'd like the Weapon to know what Creature has it is to prevent it from destroying its own Creature (when Weapon attacks, will detect all Creatures it collides with and kill them, except the Creature that has the Weapon).

Here is what the (simplified) Creature class looks like:

class Creature {
    private:
    Weapon* weapon_;
    public:
    void SetWeapon(Weapon* w){
        // do some other stuff (e.g. remove Weapon from any other Creatures)
        weapon_ = w;
        w->creature_ = this;
    }
}

Here is what the (simplified) Weapon class looks like:

class Weapon{
    friend class Creature; // Creature needs access to creature_ pointer
    private:
    creature_;
}

As you can see, I have made Creature a friend class of Weapon so that the setWeapon() method of Creature can set the private creature_ pointer appropriately.

My concrete questions:

  1. I have heard that two objects referencing each other is bad design. But in my case, how would I go about NOT doing this? I really "feel" that every Creature should know what Weapon it has and every Weapon should know what Creature has it (so that it doesn't damage that Creature). Is there any way of achieving what I want WITHOUT having these two classes reference each other? I have encountered this SAME problem over and over again in my game engine with Map/Entity, Inventory/Item, etc...It seems like whenever I have a "Container" class and an "Item" class, this referencing problem reappears. I want to put the responsibility of ADDING the item in only ONE of the classes yet I want BOTH classes to know about each other (i.e. I want the Creature to know its Weapon and the Weapon to know its Creature). Is there any way of achieving this WITHOUT having both items reference each other?

  2. Is this design sometimes necessary? Or is there a general way to always avoid it yet achieve the same type of functionality?

  3. If this design is really necessary to achieve this type of functionality, is using a friend class the proper way to handle it?

Thank you so much in advance. I am very interested in learning if there is a way to achieve this type of functionality without having the objects reference each other.

Upvotes: 5

Views: 3603

Answers (3)

Rob L
Rob L

Reputation: 2530

It is very common to have objects refer back and forth. A common example is a pointer back to a parent. Your concept is perfectly reasonable. Just make sure that you have your destructor in place so that the object pointers get cleared out.

In ~Weapon(), clear the Creature's pointer to the weapon, and vice versa.

Upvotes: 0

Alexey Andronov
Alexey Andronov

Reputation: 602

This kind of problems happen from time to time, and being resolved by the following technique:

class Creature {
public:
    void SetWeapon(Weapon* w) {
        weapon_ = w;
        weapon_->SetCreature(this);
    }
private:
    Weapon* weapon_;
};

class Weapon {
public:
    void SetCreature(Creature* _creature) {
        m_owner = _creature;
    }
private:
    Creature* m_owner;
};

As about your broad question - if you face this kind of problems pretty often in the same project, I propose you to reconsider your design solutions.
For example, your proposition about weapon to know it's creature is counterintuitive and doesn't feel right. So start with that assumption and I'm sure you end up with better design where your weapons won't know anything about their owners (like in real life!).

Upvotes: 2

usamazf
usamazf

Reputation: 3215

  1. You have heard correct. It is not a good programming practice to use reference objects in this way but then again using goto is also considered a bad approach by some. For Alternative solution see below.

  2. This design can be used as sometimes we require goto loop as well. BUt not liked approach by many.

Alternative solution: Based on what you require I can suggest an alternative approach hope this helps. Instead of making reference for each other in the their respective classes, You can create struct to accomodate both a player object and weapon object. This way it will be easier to manipulate and make changes as per desire. i.e. a player can have many weapons (you can create an array in this case in the struct). Each player will have an instance of weapon assosiated with it.

Upvotes: 0

Related Questions