Wieso Header in cpp inkludieren?



  • Mahlzeit,

    Wieso ich meinen Code in .h und .cpp splitten soll ist mir einigermassen klar: Damit ich Typen/Funktionen, die in Foo.cpp definiert sind, einfach durch Inklusion von Foo.h benutzen kann, oder?

    Was ich nicht verstehe: Wieso muss ich in Foo.cpp auch Foo.h inkludieren? 😕



  • bob.h

    class foo
    {
    public:
    void sup();
    };
    

    bob.cpp

    #include "bob.h"
    
    void foo :: sup ( )
    {
    ...
    }
    

    Ohne das include wüsste bob.cpp nichts von der Klasse foo.



  • Und wenn sich Deklarationen in .h und .c unterscheiden, z.B. wegen Weiterentwicklung, meckert der Compiler.



  • Marlin schrieb:

    Wieso muss ich in Foo.cpp auch Foo.h inkludieren? 😕

    Der Compiler weiß nicht, dass Foo.cpp und Foo.h zusammen gehören, die haben nur zufällig ähnliche Namen.



  • Also ist der eigentliche Grund, dass vor einer Definition IMMER eine Deklaration kommen muss?



  • http://www.c-plusplus.net/forum/61231-full

    EDIT: < 5 Sekunden bei Google



  • Marlin schrieb:

    Also ist der eigentliche Grund, dass vor einer Definition IMMER eine Deklaration kommen muss?

    Richtig



  • 😮 schrieb:

    Marlin schrieb:

    Also ist der eigentliche Grund, dass vor einer Definition IMMER eine Deklaration kommen muss?

    Richtig

    Aber folgendes ist doch gueltig:

    ...
    
    void foo() {
       cout << "foo";
    }
    
    int main() {
       foo();
    }
    

    Hier muss ich ja auch nicht vor der foo() Definition foo deklarieren (sprich void foo(); )
    😕



  • Definition auch gleich Deklaration



  • Er geht von oben nach unten, und wenn er unten angekommen ist war er ja schon oben und weis das es eben genau foo() schon gibt..



  • Wieso muss ich dann vor der Definition einer Methode Foo::method() (in Foo.cpp) den Foo Header Foo.h in Foo.cpp inkludieren, wenn die Definition eh auch schon die Deklartion ist?



  • Du musst den Header keineswegs immer includen. Nur wenn der Inhalt in der Implementierung verwendet wird, z.B enums, typedefs, Klassen.



  • Versuchs mal so und schau was passiert: 😉

    int main() { 
        foo(); 
    }
    
    void foo() { 
        cout << "foo"; 
    }
    

    Ja, es kommt zu einem Fehler warum das so ist hat Flutscherino ja schon erklärt.

    Über das int main kommt halt noch void foo();



  • Hi,

    also Du kannst alles auch einfach in eine C++-Datei schreiben, das klappt für die C++-Datei selbst auch. Du musst dann auch nicht zwischen Klassendefinition ohne Implementierung und Methodenimplementierung unterscheiden, beides würde funktionieren.

    Wenn jetzt andere Übersetzungseinheiten (ÜE; .cpp-Dateien) jedoch diese Klasse nutzen möchten, kennen sie die Klasse nicht. Zwar könnte der Linker der anderen ÜE die Daten bekannt machen, da sie ja in einer anderen ÜE (unserer ersten .cpp-Datei) bekannt sind, jedoch erfordert dies zumindest eine Deklaration der Methoden.

    Wie löst man das? Man schreibt die Deklaration der Klasse in eine Header-Datei und lässt diese einfach von jeder ÜE, welche die Implementation der Klasse nutzen möchte, inkludieren. Jetzt sieht der Linker für unsere zweite .cpp-Datei, welche die Klasse nutzen möchte, "Hey, für das, was er nutzen will, gibt es Deklarationen... die Definitionen liegen hier nicht rum, dann schau ich Mal, ob es die in anderen ÜE gibt"... Und dann findet er die.

    Die ganze Geschichte ist etwas umständlich. Es gibt ja auch einige, die sich dafür aussprechen, diese Header/Cpp-Zweiteilung ggü. einem mir unbekannten besseren Ansatz auszutauschen, da es schon etwas lästig ist. Aber so ist es zurzeit halt.



  • In diesem Fall musst du den Header nicht im cpp inkludieren:

    // .h
    int negate(int i);
    
    // .cpp
    
    int negate(int i)
    {
      return -i;
    }
    

    Die Implementierung im .cpp muss die Deklaration im .h nicht kennen. Wenn Du bei einer Klasse die Implementierung auslagern willst, sieht es natürlich anders aus.



  • Eisflamme schrieb:

    also Du kannst alles auch einfach in eine C++-Datei schreiben, das klappt für die C++-Datei selbst auch. Du musst dann auch nicht zwischen Klassendefinition ohne Implementierung und Methodenimplementierung unterscheiden, beides würde funktionieren.

    Trotzdem muss erst eine Klassendefinition her, oder nicht?
    Oder würde:
    bla.cpp:

    ...
    void foo::method()
    {
    }
    
    class foo
    {
       void method();
    };
    
    ...
    

    funktionieren?



  • In foo.h stehen nicht nur deklar

    😮 schrieb:

    Marlin schrieb:

    Also ist der eigentliche Grund, dass vor einer Definition IMMER eine Deklaration kommen muss?

    Richtig

    Nein, komplett falsch. Man braucht keine Deklarationen vor einer entsprechenden Definition, weil wie schon gesagt wurde die Definition selber auch eine Deklaration ist (edit: Ausnahme Definitionen von Methoden außerhalb der Klasse).

    Aber was du in foo.cpp nicht hast, dafür aber im Header ist die Definition der Klasse Foo. Und die brauchst du in der .cpp, damit der Compiler weiß, was mit void Foo::bar() gemeint ist.



  • Belli:
    Also ich bin jetzt nicht beim Terminus sicher und bitte pumuckl den Fall auch zu klären, aber:

    void foo::bar()
    {
    // ...
    }
    

    ist imo nicht zugleich Deklaration, funktioniert jedenfalls nicht. Denn für eine Deklaration einer Methode einer Klasse gehört doch auch, ob die Methode public/protected/private ist, was hier nicht angegeben ist.

    Eine Variante, die Deklaration und Definition für eine Klasse vereint, ist jedoch:

    class foo
    {
    public:
        void bar()
        {
            // ..
        }
    };
    

    Das sollte man natürlich nicht tun. Denn wenn die Klasse 10 Mal genutzt wird und man die Implementierung von bar() ändert, führt dies zu einer Neukompilierung aller ÜE, welche die Klasse nutzen.



  • 😮 schrieb:

    Marlin schrieb:

    Also ist der eigentliche Grund, dass vor einer Definition IMMER eine Deklaration kommen muss?

    Richtig

    Falsch.

    xStrykex schrieb:

    Definition auch gleich Deklaration

    Richtig.

    Aber um eine Methode einer Klasse zu definieren, muss zunächst die Definition der Klasse bekannt sein. Die Deklaration einer Klasse ist etwas völlig anderes.

    Faustregel: Wenn {} im Spiel sind, wird irgendwas definiert 😉



  • Stefan schrieb:

    In diesem Fall musst du den Header nicht im cpp inkludieren:

    // .h
    int negate(int i);
    
    // .cpp
    
    int negate(int i)
    {
      return -i;
    }
    

    Die Implementierung im .cpp muss die Deklaration im .h nicht kennen. Wenn Du bei einer Klasse die Implementierung auslagern willst, sieht es natürlich anders aus.

    ...wobei zumindest in C hier der Vorteil des Inkludierens des Headers wäre, dass der Compiler dann noch vergleichen kann, ob die Definition zur Deklaration passt. Also, bei

    // .h
    int negate(int i);
    
    // .cpp
    
    double negate(double x)
    {
      return -x;
    }
    

    würde da in C ein fertiges Programm erstellt, was nicht funktioniert und sich komisch verhält. Mit dem Inkludieren des Headers würde dieser Fehler schon zur Compile-Zeit bemerkt.

    In C++ sieht das etwas anders aus. Da würde man einen Fehler zur Linkzeit bekommen, ob man den Header nun inkludiert oder nicht, weil man ja in C++ Funktionen überladen kann und die verschiedenen Versionen in den Objektdateien auch unterschiedliche "gemangelte" Namen bekommen.

    Ich habe es mir angewöhnt, den Header immer zu inkludieren, weil man ihn eh meistens benötigt.



  • Eisflamme schrieb:

    ist imo nicht zugleich Deklaration,

    Stimmt, danke, habs bei mir reineditiert...


Anmelden zum Antworten