2

I am trying to figure out how to structure my game. I want to pass my "managers" down the hiearchy instead of making them global. But I ran into a problem. One of my managers updates scenes. It needs to pass Application reference to scenes, as application contains quit method. But my Application holds and updates this SceneManager. So my Application now includes SceneManager as it needs to update it, and my SceneManager includes Application as it needs to pass Application reference to scenes.

Basically Application holds all managers, SceneManager passes Application reference to Scenes, Scenes use managers obtained from Application reference.

// In application
sceneManager.updateScenes(*this);
// In SceneManager
currentScene.update(application)
// In scene
application.getSceneManager().doSomething()

Could anyone suggest me how to elegantly structure this part of my game? I know about forward declarations, but I would like to know if there is a solution without the need to make forward declarations.

I could use globals, but I would rather not.

Diagram

Etwus
  • 549
  • 5
  • 15
  • 1
    When you pass and store references the full class definition is not required by the header. Don't include the other header in the header; use a forward declaration of the class instead. In the implementation file it will be safe to include both headers. – user4581301 Jan 13 '20 at 20:49
  • 1
    Are you familiar with events, callbacks, signals? Using one of these patterns allows an object (i.e. `SceneManager`) to signal to its owner without having a hard dependency on the owner type. `Application` can have a `SceneManager` and assign callbacks or event handlers to the `SceneManager`'s events from the context where that `SceneManager` is created. – Romen Jan 13 '20 at 20:50
  • related/dupe: https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes – NathanOliver Jan 13 '20 at 20:57
  • Please note that I am trying to avoid forward declaration because I would need to declare application in everything that needs it's reference. (SceneManager depends on Scene, and Scene needs Application. Scene depends on GameObject, and Gameobject needs Application...) I think this signals that my whole design is useless, and that it could be resolved by sticking to some different pattern. – Etwus Jan 13 '20 at 21:02
  • The dry simple answer is let the dependencies go in one direction only. Application -> Scenemanager -> Scene -> Object. Don't start calling stuff upp the ladder, like Application from SceneManager or Scene. – super Jan 13 '20 at 21:09
  • 1
    If you do not use forward declarations you still have to have a definition of `Application` in everything that needs it. You may be able to redesign to minimize `Application`s exposure. Perhaps the [pimpl idiom](https://en.cppreference.com/w/cpp/language/pimpl) is the answer you're looking for.? – user4581301 Jan 13 '20 at 21:16

1 Answers1

2

One common (but not the only) solution to this problem is to have Scene communicate with Application through an interface which Application implements, rather than by direct reference.

This has the additional benefit of more clearly expressing what exactly Scene (and other dependencies) need to call out to.

For example:

interface ISceneHandler {
  void Quit(); // Request that we quit the game.
}

class Application : ISceneHandler {
  private SceneManager sceneManager;

  public Application() {
    // Pass ourself as the handler.
    sceneManager = new SceneManager(this);
  }

  public void Quit() { ... }
}

class SceneManager {
  private ISceneHandler handler;

  public SceneManager(ISceneHandler handler) {
    this.handler = handler;
  }

  public void SomeEvent() {
    this.handler.Quit();
  }
}
Josh Bothun
  • 1,324
  • 9
  • 9