kostenloser Webspace werbefrei: lima-city


C++ Auslagern von Methodendeklarationen

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    ansi-code

    Kostenloser Webspace von ansi-code

    ansi-code hat kostenlosen Webspace.

    Ich beschäfftige mich wenig, und wenn dann meißt mit der unterbewussten intention mein System zu schrotten als kleinen Spaß zur abwechslung von C#, habe aber ein paar Bücher darüber und sonst noch nie WIRKLICH etwas in C++ programiert.
    Also wundert euch nicht dass ich das nicht verstehe:

    VS 2008 Express, man macht nach gutem Stil eine Datei für die Klassendeklaration (header) und für die implementierung (cpp)
    die Inmplementierung macht ein
    #include "Deklaration"
    und die Deklaration macht nur ein #pragma once
    Ich habe micht mal umgeschaut und habe den Eindruck, dass das pragma irgendwas mit dem Mehrfacheinbinden der headers zu tun hat, es offenbar unterbinden soll. Ich kann den header auch 2mal einbinden und er meckert nicht, aber darum soll es jetzt nicht gehen, auf jeden Fall ist da eben kein #include

    Meine eigentliche Frage: Wenn ich in der main.cpp den header einbinde, kann er auf die implementierung zugreifen, obwohl der code der cpp Datei nirgeds included wird. Die Implementierung included den header, aber nicht umgekehrt - woher weiß der Header, wo seine implementierung liegt? In meinem Buch stand genau das nicht drinn. Danke im Voraus.

    Beitrag zuletzt geändert: 22.10.2009 21:48:41 von ansi-code
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. c****s

    Uhuhu, du schmeißt da einiges Durcheinander. Die Magie passiert beim linken.

    Die Trennung zwischen Header und Code kommt noch aus C-Zeiten und folgendes auf sich:
    In C (wie auch in C++) müssen Routinen und Variablen zuerst deklariert werden und dann definiert werden.
    Die Deklarationen (der Teile, die von außen genutzt werden sollen), werden in der Headerdatei gehalten.
    Die Definitionen in der Codedatei.
    Wenn man nun das ganze zusammenbaut, erstellt (make) und daraus lauffähigen Code macht, ruft man zuerst den Kompiler auf.
    Dieser Kompiliert alles und wenn man z.B. in der crazy.c eine Routine aus der imbecile.c aufruft, ohne in der crazy.c die imbecile.h eingebunden zu haben, dann schreit der Kompiler: "Wat soll das sein, das kenn ich ja garnicht."
    Wenn man die Header eingebunden hat, dann sagt er "Ja, OK, die Methode oder Variable ist deklariert und ich kenne die Synopsis. Was sie im Detail tut ist mir ja egal und erst zur Laufzeit wichtig."
    Danach kommt der Linker. Der löst nun alle externen Verweise auf und es kommt lauffähiger Code hinten raus.

    Sprich: Durch das einbinden der Header, macht man die dort deklarierten Variablen und Methoden bekannt.

    ansi-code schrieb:Wenn ich in der main.cpp den header einbinde, kann er auf die implementierung zugreifen, obwohl der code der cpp Datei nirgeds included wird.

    Die cpp-Datei wird zu einer Objektdatei kompiliert und der Linker packt dann die Binaries zusammen. Sonst könntest du ja auch keine externen Bibliotheken wie QT oder deine Windows- oder Linux-API nutzen.

    ansi-code schrieb: Die Implementierung included den header, aber nicht umgekehrt - woher weiß der Header, wo seine implementierung liegt?

    Einzig und allein durch seinen Namen. foo.h ist der Header von foo.c oder foo.cpp. Ob .c oder .cpp ist egal, weil der Linker, den das ganze ja erst interessiert, eh nur foo.o anzieht.

    ===============================
    EDIT: Dieses #pragma once dient - wie du richtig erkannt hast - dazu, zu verhindern, dass eine Header mehrmals angezogen wird. Denn es darf ja jede Deklaration nur genau einmal geben. Beim zweiten mal einbinden, würde der Kompiler schreien "Die routine foo (bar) wurde bereits deklariert. Tschüß".

    Dieses #pragma once ist neumodischer Scheiß, in old-skool-style sieht das ganze so aus:
    #ifndef __GANZ_WILDES_SYMBOL_UM_KOLLISIONEN_ZU_VERMEIDEN
    #define __GANZ_WILDES_SYMBOL_UM_KOLLISIONEN_ZU_VERMEIDEN
    
    void foo (int bar, int baz);
    
    #endif


    Beitrag zuletzt geändert: 22.10.2009 23:31:39 von census
  4. Autor dieses Themas

    ansi-code

    Kostenloser Webspace von ansi-code

    ansi-code hat kostenlosen Webspace.

    Nur über den Namen also. Vielen Dank. Jetzt habe ich es verstanden. :biggrin:
  5. c****s

    ansi-code schrieb:
    Nur über den Namen also. Vielen Dank. Jetzt habe ich es verstanden. :biggrin:


    Verdammt, ich hab mich sehr unglücklich ausgedrückt und dich auf ein falsches Pferd gesetzt.
    Es ist eine Konvention dass die Header so heißen wie ihr Sourcecodedateien. Mehr nicht.

    Du bindest die Headerdatei ja auch in derjenigen Datei ein, die die Methoden definiert. Die Headerdatei kann folglich heißen wie sie will.
    Ein Beispiel:
    // gurkensalat.h
    #pragma once
    
    int square (int a);


    // fib.c
    #include "gurkensalat.h"
    
    int square (int a) { return a*a; }


    // project.c
    #include <stdio.h>
    #include "gurkensalat.h"
    
    int main (void) { printf ("%d\n", square (5) ); }


    Das funktioniert auch ohne Probleme. Da der Gurkensalat in beiden C-Dateien eingebunden wird, ist an beiden stellen die Routine square deklariert und es kann ohne Probleme kompiliert werden. Wenn nun der Linker die project.o und square.o zusammenlinkt, wird der externe Verweis aus project auf square aufgelöst.

    Beitrag zuletzt geändert: 23.10.2009 14:31:58 von census
  6. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!