'C++ object hierarchy - how to manage circular dependencies?

I want to make two classes: an object and an object_manager, but I'm confused about how they should see/include each other. I've heard that it's forbidden for two headers to include each other and if my code dependencies has circles then it's a bad code design and usually it should be like a hierarchy structure (town->house->furniture and furniture shouldn't know about town existence).

But here I have the object_manager which knows and holds all the objects, and the objects should have an option to create new objects, but then they should call the object_manager which will force them to know about it existence and this will create a circle in the structure, which is bad.

It's like one process wants to create a new process by calling the OS system calls, so the OS and the process knows about each other.

Is there a way I can implement this in the right code design, or should it just be bad sometimes?

I thought maybe the objects should have a special place where they will store all their "system calls", and the object_manager will check it from time to time, but maybe there is a better way.



Solution 1:[1]

Use forward declaration:

class ObjectManager;

class Object
{
private:
   ObjectManager* m_objManager;
   ....
public:
   ....
};

In .cpp file you can include the ObjectManager.h Also instead of ObjectManager make the interface which will give you more abstraction for implementation IObjectManager.

Solution 2:[2]

Actually it is possible to implement the two. And no it's not really bad. Here is some partial code.

let's say you have a header file

myobject.h

#ifndef _MYOBJECT
#define _MYOBJECT
// Declare the Object Manager class in it.

class MyObjectManager; // forward declaration

class MyObject {
      MyObjectManager manager;
      registerSelf(MyObjectManager &m);
}

#endif _MYOBJECT

Now for the ObjectManager header

#ifndef _MYOBJECT_MANAGER
#define _MYOBJECT_MANAGER

class MyObject;  // forward declaration

class MyObjectManager {
      private:
                List list[];
      public:
                registerObject(MyObject &o);
};

#endif

Implementation of objectmanager

#include <myobject>
#include <myobjectmanager>

MyObjectManager::manageMyObject(MyObject &o) {
   list += o; /* etc.  */
}

Implementation of object

#include <myobject>
#include <myobjectmanager>


MyObject::registerSelf(MyObjectManager &manager) {
     this.manager = manager;
     manager.registerObject(*this);
}

Solution 3:[3]

There are many cases where classes need to know about each other. The only issue with this is they have to know about each other partially or at least one class does. The way the issue is generally solved is using forward declarations . The only sticky issue is in class A you can't declare a member that has a type of class B only a pointer or a reference to Class B.

class B;
class A 
{
   B* oB;

};

class B
{
   A oA;
}:

Solution 4:[4]

Some general recommendations to remove the coupling between headers follow:

Forward Declare what you can. Sometimes your A class uses others classes (X,Y,..) only by passing references or pointers. So in your A.h you can declare methods that use these X,Y return or argument types without the compiler needing to know the complete type. That means that A.h does not need to include X.h or Y.h

Use PImpl idioms, Sometimes the best way to decouple implementation from interface (without using virtual or abstract classes) is doing something like:


Foo.h

class Foo {
struct Impl;
Impl* m_impl;

public:
Foo();
void SomeMethod();

}

Foo.cpp

#include "X.h"
struct Foo::Impl {
/* actual implementation */
...};

Foo::Foo() : m_impl( new Foo::Impl() ) {};

void Foo::SomeMethod() {
m_impl->SomeMethod();
}

Solution 5:[5]

What you're describing is an object that can only exist inside another object.

A good way to implement this is with nested classes:

class object_manager {
  public:
  class object {  // object_manager::object. public allows it to be used outside of manager
    public:
    void foo() {
      object* t = construct(); // can call object_manager methods
    }
  };

  private:
  object my_objects[5]; // can create objects
  static object* construct() { return NULL; }
};

Keep in mind that you can still have 2 cpp files for object and object_manager.

Solution 6:[6]

The CPP files can include each other's headers without causing a compile problem (whether it's correct from a design point of view is a different matter, but should be ok in yur case). This means they can call each other's methods, etc.

Regarding the header files, the "object manager" header will most likely include the "object" header because the "object manager" class needs to work with "object" class instances. If the "object" header file needs to know about the "object manager" class, place a forward declaration for the "object manager" in the "object" header file. That way you can use pointers and references to the "object manager" in the "object" header file without creating a circular include dependency.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TylerH
Solution 2 Ahmed Masud
Solution 3 rerun
Solution 4
Solution 5
Solution 6