Frage zu #include ?



  • Hallo liebe C++ Gemeinde .
    Ich habe mal eine kurze Frage zu der Include Anweisung .
    Nehmen wir mal an ich habe folgende main.cpp

    #include "Header.h"
    int main()
    { 
     func(10); 
     return 0 ;
    }
    
    //HEADER.h
    int func(int);
    
    //HEADER.cpp
    #include "Header.h"
    int func(int a)
    {
     return a*a;
    }
    

    Meine Fragen dazu :
    Woher weiß meine main.cpp wo sie die Definiton der Funktion func findet ?
    Denn nach dem kompilieren steht ja nur die Deklaration innerhalb der main aber keine Definiton. 😕

    Und warum genau muss ich in meiner HEADER.cpp die HEADER.h einbinden ?

    Welche und wie viele Dateien enstehen nach dem kompilieren von diesem Code Beispiel ? Bekomme ich für jede .cpp + .h einen Objekt Datei ? Und werden diese Objekt Dateien dann vom Linker gebunden und zu einer ausführbaren Datien gelinkt ?

    Mfg


  • Mod

    Bacid90210 schrieb:

    Meine Fragen dazu :
    Woher weiß meine main.cpp wo sie die Definiton der Funktion func findet ?
    Denn nach dem kompilieren steht ja nur die Deklaration innerhalb der main aber keine Definiton. 😕

    Das weiß deine main.cpp nicht. Es wird einfach Code erzeugt der eine Funktion aufruft, die den Vorgaben im Header entspricht, dazu muss nichts näheres über die Funktion bekannt sein.

    Und warum genau muss ich in meiner HEADER.cpp die HEADER.h einbinden ?

    Musst du nicht, wenn du nicht möchtest. Ist aber oft sinnvoll, da man die Deklarationen aus dem Header ja auch benutzen möchte.

    Welche und wie viele Dateien enstehen nach dem kompilieren von diesem Code Beispiel ?

    Das kommt ganz darauf an, wie genau du Compiler und Linker aufrufst.

    Bekomme ich für jede .cpp + .h einen Objekt Datei ?

    Das kommt ganz darauf an, wie genau du Compiler und Linker aufrufst. Eines der üblichen Szenarien, ist für jede cpp-Datei eine Objektdatei zu erzeugen. Das andere gängige Szenario ist es, gar keine Dateien zu erzeugen (bzw. bloß irgendwo temporär) und direkt zum Linken überzugehen.

    Und werden diese Objekt Dateien dann vom Linker gebunden und zu einer ausführbaren Datien gelinkt ?

    Das kommt ganz darauf an, wie genau du Compiler und Linker aufrufst. Aber das was du beschreibst ist der übliche Anwendungszweck eines Linkers.



  • Ok , meine Main weiß also nichts von der Funktionalität .
    Sie kennt lediglich die Deklaration falls ich nur die Header eingebunden habe.
    Wie kann sie dennoch die Funktionalität nutzen ?
    Ist dies ebenfalls die Aufgabe des Linkers ?



  • Ein #include kopiert einfach den Quellcode aus dem Header in die main.cpp, daher hat sie die Deklaration 😉



  • 314159265358979 schrieb:

    Ein #include kopiert einfach den Quellcode aus dem Header in die main.cpp, daher hat sie die Deklaration 😉

    Das ist mir schon klar. Allerdings beantwortet das nicht meine Frage.


  • Mod

    Bacid90210 schrieb:

    Wie kann sie dennoch die Funktionalität nutzen ?
    Ist dies ebenfalls die Aufgabe des Linkers ?

    Genau so ist es.



  • Erstmal Dankeschön. Das hilft mir schon mal weiter das Konzept zu verstehen.
    Die verschiedenen cpp Dateien leben also bis zum linken unabhängig voneiander.
    Und die Header hat lediglich die Aufgabe den Dateien in denen sie eingebunden ist mitzuteilen dass die definierten Funktion zur Laufzeit existieren.
    Die Header.h binde ich dann bestimmt auch in die Header.cpp ein um das Abgleichen mit den Prototypen sicher zu stellen oder ?


  • Mod

    Bacid90210 schrieb:

    Erstmal Dankeschön. Das hilft mir schon mal weiter das Konzept zu verstehen.
    Die verschiedenen cpp Dateien leben also bis zum linken unabhängig voneiander.
    Und die Header hat lediglich die Aufgabe den Dateien in denen sie eingebunden ist mitzuteilen dass die definierten Funktion zur Laufzeit existieren.

    Genau. Außerdem verrät der Header nicht nur die Existenz einer Funktion, sondern auch alles was man wissen muss, um sie richtig aufzurufen. Das ist wichtig sowohl um die Konsistenz des Programms zu prüfen (z.B. ob die richtige Anzahl und der richtige Typ von Parametern übergeben wurde) als auch um den eigentlichen Aufrufmaschinencode zu erzeugen.

    Die Header.h binde ich dann bestimmt auch in die Header.cpp ein um das Abgleichen mit den Prototypen sicher zu stellen oder ?

    Auch. Kommt auch auf die benutzten Sprachfeatures an. Im Header stehen ja nicht nur Funktionsprototypen, sondern möglicherweise auch Definitionen von Konstanten, Templates, Klassen oder gar Makros die irgendwie mit der Funktionalität dieses Moduls zu tun haben. Die möchte man ja nicht alle noch einmal in der cpp-Datei eintippen (was technisch möglich wäre), wenn man auch einfach den Header einbinden kann. Und ja: Dadurch wird natürlich auch vieles automatisch auf Konsistenz geprüft. Bei Funktionen ironischerweise aber gerade nicht, da nicht klar ist, ob es sich bei abweichenden Signaturen in cpp-Datei und Header um einen Fehler handeln soll oder ob durch die Deklaration aus dem Header eine Überladung der Funktion bekannt gemacht werden soll.



  • Super .Ich dank dir .
    Gute Nacht.
    🙂



  • Du kannst folgendes ausprobieren, um das Konzept zu verstehen: rufe weiterhin in deiner main die Funktion func auf. Und lasse die header.cpp leer, so das die Definition von func fehlt. Dann kompilierst du nur die main, und du wirst sehen, das der Compiler nicht meckert.

    Aber so bald du linkst, wird der Linker meckern, das die func nicht zu finden ist.
    Für einen Anfänger, der diesen Fall ungewollt produziert, kann das wirklich demotivierend sein.


Anmelden zum Antworten