zyklische Abhängigkeiten und forward declarations



  • Hi, ich habe folgende zyklische Abhängigkeit in meinem Design:

    • scene.hpp enthält die Deklaration einer Klasse Scene , die eine Spielszene beschreibt.
    • gameobject.hpp enthält die Deklaration einer Klasse GameObject , die ein einzelnes Objekt der Spielszene beschreibt.
    • Eine Scene besitzt mehrere Instanzen von GameObject => scene.hpp benötigt das Symbol GameObject .
    • Ein GameObject kennt die Scene zu der es gehört => gameobject.hpp benötigt das Symbol Scene

    .. 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; in gameobject.hpp zu machen und im anderen Header schon mit include zu arbeiten (d.h. #include "gameobject.hpp in scene.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.


Log in to reply