Ring- "#include <header>" von Dateien auflösen



  • Hallo,

    diese Problematik gibt es sicherlich im Programmier-Alltag, aber den Begriff kenne ich nicht... gegeben sind drei Dateien, welche sich durch die include Aufrufe zu einem "Ring" zusammenschliessen a la:

    //Datei eins.h
    #include "zwei.h" ...
    
    //Datei zwei.h
    #include "drei.h" ...
    
    //Datei drei.h
    #include "eins.h" ...
    

    Mein Compiler meckert nun Deklarationen an, welche in "eins.h" stehen (warum weiß ich nicht ?), lösche ich nun die Include-Anweisung in drei.h, läßt sich der andere Teil vom Compiler interpretieren, aber Deklarationen von "eins.h" in "drei.h" werden dafür (natürlich zu recht) nicht gefunden.

    Wie löse ich diesen Ring auf ? Geht das überhaupt ?

    Winn



  • Schreib in Jeden Header sowas:

    #ifndef HEADERNAME_INCLUDED
    #define HEADERNAME_INCLUDED
    
    // Hier dein Header
    
    #endif
    

    Dann sollten alle Header nur einam includeiert werden. (HEADERNAME musst du natürlich sinnvoll ersetzen, für jeden Header anders.



  • darthdespotism schrieb:

    #ifndef HEADERNAME_INCLUDED
    #define HEADERNAME_INCLUDED
    
    // Hier dein Header
    
    #endif
    

    Das habe ich nun gemacht (siehe unten) - trotzdem habe ich diese Compiler-Fehlermeldungen, gibt es noch eine andere Fehlerquelle ?

    //Datei eins.h
    #ifndef _EINS_H_
    #define _EINS_H_
    
    #include "zwei.h" ...
    
    #endif
    
    //Datei zwei.h
    #ifndef _ZWEI_H_
    #define _ZWEI_H_
    
    #include "drei.h" ...
    
    #endif
    
    //Datei drei.h
    #ifndef _DREI_H_
    #define _DREI_H_
    
    #include "eins.h" ...
    
    #endif
    


  • Winn schrieb:

    Das habe ich nun gemacht (siehe unten) - trotzdem habe ich diese Compiler-Fehlermeldungen, gibt es noch eine andere Fehlerquelle ?

    Du darfst schlicht und ergreifend keine Ringabhängigkeiten in C++ machen (den wo soll der Compiler bitte mit dem Auflösen beginngen). Was du machen kannst ist mit Vorwärtsdeklarationen zu arbeiten. Dies geht solange im Header die Klasse nur als Referenz oder Pointer verwendet wird. Den eigentlichen Include machst du dann im Souce (cpp):

    // a.h
    #if !defined(CLASS_A_HEADER)
    #define CLASS_A_HEADER
    
    class B; // Vorwärtsdeklaration
    
    class A
    {
      ...
      // Ein paar Möglichkeiten bei Vorwärtsdeklaration:
      B* member;
      void foo(const B& b);
      B* foo();
      ...
    }
    
    #endif
    
    // a.cpp
    #include "a.h"
    #include "b.h"
    ...
    

    cu André



  • Super ! Danke für den Tip mit der Vorwärtzdeklaration - das hat funktioniert...



  • Solange du (vor allem in Headern) nur Referenzen und Pointer auf einen Typ deklarierst und den Typ selbst (bzw. seine member) nicht benutzt, bietet sich die Vorgehensweise mit der Vorwaertsdeklaration eigentlich immer an, nicht nur um Ringincludes aufzuloesen. Das reduziert die Abhaengigkeiten des Compilers und verhindert, dass du jedesmal die ganze Welt neu kompilieren musst, wenn du z.B. eine Klassendeklaration aenderst, die du eigentlich nicht ueberall brauchst.
    Herb Sutter hat einen kleinen Artikel geschrieben der das veranschaulicht: http://www.gotw.ca/gotw/007.htm


Anmelden zum Antworten