zyklische Abhängigkeiten und forward declarations
-
Hi, ich habe folgende zyklische Abhängigkeit in meinem Design:
scene.hpp
enthält die Deklaration einer KlasseScene
, die eine Spielszene beschreibt.gameobject.hpp
enthält die Deklaration einer KlasseGameObject
, die ein einzelnes Objekt der Spielszene beschreibt.- Eine
Scene
besitzt mehrere Instanzen vonGameObject
=>scene.hpp
benötigt das SymbolGameObject
. - Ein
GameObject
kennt dieScene
zu der es gehört =>gameobject.hpp
benötigt das SymbolScene
.. also eine klassische zyklische Abhängigkeit. Ich wüsste nicht wie ich diese Abhängigkeit sinnvoll brechen kann. Ist es sinnvoll und legitim hier forward declarations zu verwenden und erst in der Implementierung die entsprechenden Header einzubinden? D.h.
// scene.hpp class GameObject; // Rest der ursprünglichen Deklaration
// scene.cpp #include "scene.hpp" #include "gameobject.hpp" // Rest der ursprünglichen Implementierung
// gameobject.hpp class Scene; // Rest der ursprünglichen Deklaration
// gameobejct.cpp #include "gameobject.hpp" #include "scene.hpp" // Rest der üblichen Implementierung
Denkbare wäre auch, die forward declaration nur in einem der Header (d.h. z.B.
class Scene;
ingameobject.hpp
zu machen und im anderen Header schon mitinclude
zu arbeiten (d.h.#include "gameobject.hpp
inscene.hpp
).Rein technisch funktioniert das .. nur ist die Frage ob das hier noch best practise oder eher schon "Bekämpfung der Symptome" ist...
LG Glocke
-
Meiner Meinung nach macht es immer Sinn mit Forward Declarations zu arbeiten und den Header nur dann einzubinden, wenn die komplette Klassendefinition auch tatsächlich benötigt wird. Das hilft nicht nur solche zyklischen Abhängigkeiten zu brechen, sondern reduziert auch generell die Abhängigkeiten der Header untereinander. Wenn so ein Projekt mal größer wird führt ansonsten jede kleine Änderung in einer Header-Datei dazu, dass große Teile des Projekts neu kompiliert müssen (weil die in den cpp-Dateien eingebundenen Header dann oft "über etliche Ecken" von dem Header abhängig sind, an dem du gerade Änderungen vorgenommen hast)
Generell: Wenn du nur einen (Smart-)Pointer auf die Klasse verwendest, dann empfiehlt sich eine solche Forward Declaration. Wenn du von der Klasse ableitest, oder diese z.B. ein nicht-Pointer-Member im aktuellen Header ist, kommst du allerdings nicht drum herum, auch den Header der Klasse einzubinden, weil dafür die komplette Definition bekannt sein muss.
Wenn in deinen Headern nur (Smart-)Pointer auf die andere Klasse auftreten (ohne diese zu kennen vermute ich das mal), würde ich also aus den o.g. Gründen in beiden mit einer Forward Declatation abreiten und die jeweiligen Header erst in der .cpp-Datei einbinden (dort, wo die komplette Klassendefinition auch wahrscheinlich tatsächlich erst benötigt wird).
Finnegan
-
Die <GameObject.h> kann auch am Anfang die Scene vorausdeklarieren und dann die <Scene.h> am Ende inkludieren. Dann haben sich die beiden Headers doch gegenseitig inkludiert, ohne zu weinen.