Kann man nicht Datei 1 in Datei 2 includen und gleichzeitig in Datei 2 Datei 1



  • Da hat sich doch glatt der Fehlerteufel eingeschlichen, hier die korrigierte Version

    Tippgeber schrieb:

    Luke-2 schrieb:

    Hi

    die Frage steht schon im Titel. Kann ich nicht in Datei 1 eine andere Datei includen und in dieser dann wiederrum Datei 1?

    Stell dir mal folgendes vor: du hast zwei Kartons, ich nenne diese mal Karton A und Karton B. Jetzt versuche einmal Karton A zusammenzufalten und in Karton B zu legen und danach Karton B zusammenzufalten und in Karton A zu legen.
    Falls du das schaffst kannst du das Prinzip auf die beiden Dateien übertragen.

    Und falls nicht schau dir mal Forwärtsdeklarationen (forward declarations) an.



  • Fragt sich jetzt, wozu das ueberhaupt gut sein soll.
    Was willst du denn machen?
    Sehe dabei keinen Sinn zwei Headerdateien gegenseitig zu includen.

    gruss
    Cartman



  • geht schon:

    a.cpp:

    #define A
    const char *b = "hallo";
    #ifndef B
    #include "b.cpp"
    #endif
    

    b.cpp:

    #define B
    #ifndef A
    #include "a.cpp"
    #endif
    
    #include<stdio.h>
    
    int main(){ printf("%s\n", b); }
    

    g++ -c a.cpp; g++ -c b.cpp; g++ b.o



  • Luke-2 schrieb:

    Hi

    die Frage steht schon im Titel. Kann ich nicht in Datei 1 eine andere Datei includen und in dieser dann wiederrum Datei 1?

    Tippgeber hat das ja schon richtig beschrieben noch einfacher wirds wenn du dir das ganze wie eine Liste vorstellst, bei datei 1 gehts los, drin steht include 2 also wird die 2 reingehauen in der Steht include 1 also landet die 1 zum 2. mal drin usw, das ganze dreht sich dann endlos lang im Kreis bis der Compiler es aufgibt.



  • Also mit Include-Guards geht das schon.
    Der Sinn? Nuja oft mal Übersichtlichkeit...

    // ------------------------------------
    // foo.hpp
    #ifndef FOO_HPP_INCLUDED
    #define FOO_HPP_INCLUDED
    
    // und/oder
    #pragma once
    
    class foo
    {
    public:
        void bar();
        // ...
        // ...
        // ...
    };
    
    #include "foo.inl"
    
    #endif // FOO_HPP_INCLUDED
    
    // ------------------------------------
    // foo.inl:
    
    #ifndef FOO_INL_INCLUDED
    #define FOO_INL_INCLUDED
    
    // und/oder
    #pragma once
    
    #include "foo.hpp"
    #include <conio.h>
    
    inline void foo::bar()
    {
        printf("42");
    }
    
    // ...
    // ...
    // ...
    
    // ...
    // ...
    // ...
    
    #endif // FOO_INL_INCLUDED
    


  • hustbaer schrieb:

    Also mit Include-Guards geht das schon.
    Der Sinn? Nuja oft mal Übersichtlichkeit...

    Das ist aber nicht das Selbe. Wie man in u_ser-l's Beispiel sieht packt man mit diesem Trick in jede Datei mehrere "Dateien" und kann immernoch nicht alle gleichzeitig nutzen, denn g++ a.cpp b.c++ schlägt weiterhin fehl.
    Und genau darum geht es doch eigentlich, dass man eben nicht den Code von Datei 1 in dem Code von Datei 2 und umgekehrt gleichzeitig verwenden kann. Dafür gibt es doch die Forwärtsdeklaration, Zeiger und Funktionsdeklarationen 🙂



  • Tippgeber schrieb:

    hustbaer schrieb:

    Also mit Include-Guards geht das schon.
    Der Sinn? Nuja oft mal Übersichtlichkeit...

    Das ist aber nicht das Selbe. Wie man in u_ser-l's Beispiel sieht packt man mit diesem Trick in jede Datei mehrere "Dateien" und kann immernoch nicht alle gleichzeitig nutzen, denn g++ a.cpp b.c++ schlägt weiterhin fehl.
    Und genau darum geht es doch eigentlich, dass man eben nicht den Code von Datei 1 in dem Code von Datei 2 und umgekehrt gleichzeitig verwenden kann. Dafür gibt es doch die Forwärtsdeklaration, Zeiger und Funktionsdeklarationen 🙂

    Was "dasselbe" ist interessiert mich nicht.

    Ich habe mich auf die ursprüngliche Fragestellung bezogen, und nicht auf u_ser-l's Posting.



  • Das #ifndef hab ich gemacht. Wieso ich halt frage ist folgendes: Ich hab eine Klasse "Globals" (und ja ich weiß Globale Variabeln (wofür ich die klasse tatsächlich verwende) sind ganz böse und gar nicht C++ und buuuh, und so weiter, ich mach das für ein projekt was DI abgegeben werden muss und ich hab wirklich kaum noch zeit und da wird das ende quick-and-dirty), die so aussieht:

    Globals.h:

    #ifndef GLOBALS_H
    #define GLOBALS_H
    
    #include "Controls.h"
    #include "MainMenu.h"
    #include "DocumentViewer.h"
    
    class Globals {
    
    private:
    	static Controls *control_handler;
    	static MainMenu *main_menu;
    	static DocumentViewer *document_viewer;
    
    public:
    	static void set_ch(Controls *ch);
    	static void set_mm(MainMenu *mm);
    	static void set_dv(DocumentViewer *dv);
    
    	static Controls* get_ch();
    	static MainMenu* get_mm();
    	static DocumentViewer* get_dv();
    };
    
    #endif
    

    Ich include die in meiner main-datei und benutze auch Methoden aus der Klasse - ohne fehler. Wenn ich jetzt die Datei in "MainMenu.h" (welche wiederum in Globals.h includiert ist (siehe code)) includiere bekomme ich folgende fehler:

    In file included from MainMenu.h (27) ,
                     from MainMenu.cpp (4) :
    Globals.h (13) : error: ISO C++ forbids declaration of 'MainMenu' with no type
    Globals.h (13) : error: expected ';' before '*' token
    Globals.h (18) : error: 'MainMenu' has not been declared
    Globals.h (22) : error: ISO C++ forbids declaration of 'MainMenu' with no type
    Globals.h (22) : error: expected ';' before '*' token
    

    Zeile 13 ist

    static MainMenu *main_menu;
    


  • Diese gegenseitige Abhängigkeit funktioniert nicht. Für Globals muss MainMenu bekannt sein und umgekehrt. Wie soll das gehen? Wie schon erwähnt stellen hier Vorwärtsdeklarationen eine Möglichkeit dar, da du innerhalb der Klasse nur Zeiger verwendest.

    P.S. Eine Globals -Klasse ist nicht schöner als freie globale Variablen. Da machst du lieber einen Namensraum... 😉



  • Versuchs wie Nexus bereits gesagt hat mal mit Forwärtsdeklarationen. Was auch gut Funktioniert ist die globalen in den cpp Dateien zu haben statt in den headern, um sie in mehreren cpp Dateien gleichzeitig zu nutzen gibt es das Schlüsselwort extern, kannst du dir ja mal anschaun.



  • Xebov schrieb:

    Was auch gut Funktioniert ist die globalen in den cpp Dateien zu haben statt in den headern, um sie in mehreren cpp Dateien gleichzeitig zu nutzen gibt es das Schlüsselwort extern, kannst du dir ja mal anschaun.

    Das läuft etwa auf das gleiche hinaus wie static -Variablen in Klassen und hat nicht direkt mit dem Problem zu tun.



  • Hmmm irgendwie krieg ich das nicht gebacken, und ich hab auch bei google nix passendes dafür gefunden. Wennn ich das mit der forward declarations so mache dass ich in der Datei MainMenu.cpp statt dem "#include Globals.h" "class Globals;" schreibe kommt folgende Fehlermeldung:

    MainMenu.cpp (142) : error: incomplete type 'Globals' used in nested name specifier
    MainMenu.cpp (144) : error: incomplete type 'Globals' used in nested name specifier
    

    Das (Zeile 142 und 144) sind die einzigen beiden Zeilen wo ich was aus der Globals-Klasse verwende:

    Globals::get_dv()->open_file("test.txt");
    Renderer::flush_gui_objects();
    Renderer::add_gui_object(Globals::get_dv());
    

    Was der Fehler sagt versteh ich, nur wie geh ich damit um, dazu hab ich nichts gefunden.



  • Du musst schauen, dass der Typ zum Zeitpunkt der Verwendung (in deinen beiden Zeilen) bekannt ist. Also muss der Header dann eingebunden sein - ich würde ihn gleich in die CPP-Datei, in der die Klasse verwendet wird, inkludieren.



  • Vielen Dank, dachte irgendwie die Forward declaration würde das include ersetzen, aber jetzt hab ich's geschnallt, danke!



  • Nein, die Vorwärtsdeklaration sagt dem Compiler nur, dass es einen Typ mit diesem Namen gibt. So können beispielsweise Zeiger darauf deklariert werden. Sobald man jedoch den Typen verwendet (z.B. eine Instanz erstellt, auf Klassenattribute zugreift, Werte ändert, den sizeof -Operator anwendet, ...), muss dieser vollständig definiert sein.


Anmelden zum Antworten