C++ : Headerdateien

...komplette Frage anzeigen

2 Antworten

Der sinn von Header Dateien ist Generell Dein Projekt in mehrere Module Aufzuteilen. In einer headerdatei werden vorwärtsdeklarationen für Funktionen oder variablen hinterlegt. Zudem Sollten sich Sämtliche Klassen im Header Befinden. Wichtig ist, das du im header nur Deklarierst, niemals Definierst (siehe beispiel). Ausnahmen bilden zbs. Templates.

MyFirstHeader.h:

#pragma once//ist wichtig, damit du die header datei nicht mehr als einmal inkludierst, mehr siehe Beispiel 2. pragma once funktioniert jedoch nicht unter jeder IDE, ansonnsten verwende ifndef/Include guards.
#ifndef _H_MYHEADER_//wenn _H_MYHEADER_ nicht definiert ist...
#define _H_MYHEADER_ //definiere es und füge den nachfolgenden code bis #endif ein.      (includeguards, für besseres verstehen setze dich mit dem Preprocessor auseinander.)

extern int MeineVariable;//definier eine Globale Variable. extern sagt aus, das die Variable nicht hier im header sondern in der .cpp datei definiert ist.

void MeineFunktion(int Test);//Bildet einen Prototyp für eine Funktion. Der Rumpf der Funktion folgt immer in der .cpp datei.

class MeineKlasse//die klasse an sich wird immer im header deklariert.
{
public:
      void MeineMemberFunktion();
private:
     int Test;//hier ist kein extern von nöten, da sich Test inerhalb der Klasse Befindet.
};
#endif

MyFirstHeader.cpp

#include "MyFirstHeader.h"//um die im header Deklarierten Elemente verwenden zu Können schließen wir diesen ein.

int MeineVariable=2000;//Definiert MeineVariable und setzt einen startwert von 2000.

void MeineFunktion(int Test)//in der .cpp datei ist die volle Funktion mit Rumpf definiert.
{
       //tue irgendetwas
}

MeineKlasse::MeineMemberFunktion()//wir Definieren eine Member funktion, genauso wie eine Funktion mit Rumpf. Die Klasse Muss der Member Funktion jedoch vorangestellt werden.
{
     //tue irgendetwas
}
//die Definition von membervariablen ist bereits in der Klasse Erledigt, da nicht extern.

Nun haben Wir eine .h Datei welche die Elemente vor deklariert und eine .cpp Datei die sie genauer definiert. unter C/C++ solltest du niemals eine .cpp datei direkt einschließen, sondern immer den header:

main.cpp

#include "MyFirstHeader.h"

schließt den Header ein und macht Sämtliche in der Header Datei und dazugehörigen .cpp Datei definierten Klasse/Funktionen etc. verfügbar. #include tut im Prinzip nicht mehr als den Code aus der .h Datei zu Kopieren und in main.cpp Einzufügen. Daher auch die Includeguards. Währen sie nicht, währe es ohne Weiteres möglich dass wir eine Datei mehrfach einschließen und somit alle Symbole auch mehrfach deklarieren und definieren. Das Ergebnis währen jede menge Linkerfehler.

Du solltest immer darauf achten das .h dateien sich nicht gegenseitig inkludieren. dh. Header A darf header B Inkludieren. Wenn header A header B Inkludiert, darf Header B in keiner Form header A wieder Inkludieren.

Ich hoffe ich konnte dir weiterhelfen. Eigentlich sind header Dateien das einfachste von der welt.. wenn du erstmal das Grundprinzip versanden hast. :D

LG SK

Danke, bei vielem hast du mir geholfen und mich bestätigt. Aber woher weiß der Compiler, welche .cpp-Datei den Header einbindet?

Wenn man eine Objektdatei und einen Header hat, reicht ja der Header um die kompilierte Objektdatei einzubinden.

Und was ist ein "vorkompilierter" Header?

Und warum müssen Klassen immer im Header liegen?

Und kannst du das mit dem "extern" nochmal genauer erklären?

0
@PerfectMuffin

Der Compiler muss die .cpp Dateien überhaubt nicht zuordnen, da so oder so Alle .cpp Dateien die direkt in deinem Projekt liegen compiliert werden. dh. der code würde Später ungefähr so aussehen.:

Vorwärtsdeklarationen(Test.h)
   void TestFunc();//ab hier an ist TestFunc für den Aufruf verfügbar.

aufruf(main.cpp)
   ...
   TestFunc();//TestFunc wird aufgerufen. Dies ist möglich da Test.h vorher inkludiert wurde, die vorwärtsdeklaration also über dem Aufruf steht.
   ...

Definition(Test.cpp)
   TestFunc()//Definiert die Funktion. Es ist völlig egal ob die Definition über oder unter dem Aufruf steht, da die vorwärtsdeklaration sich oberhalb des Aufrufes befindet.
   {
   }

dh. alle Definitionen die sich in deinem Projekt befinden werden auf mit kompiliert. Das gilt natürlich nicht für Dateien Außerhalb deines Projektes. Für diesen Zweck gibt es .lib/.a Dateien die den Code aus der .cpp enthalten. Diese musst du dann auch über #pragma comment(lib,"Test.lib") selber linken.


Wenn klassen in der .cpp datei liegen, währen sie von Außen ja gar nicht zugänglich. Du könntest also von einer Klasse die in der .cpp Datei liegt gar keine Instanz erstellen.


extern Spezifiziert das die Deklaration der nachfolgenden Variable nicht im header sondern erst später geschieht. Eine nicht als extern Spezifizierte Variable würde direkt im header definiert werfen. Das führt zu Linker Fehlern.(LNK2005) Da versucht wird die Variable mehrfach zu Definieren.


zu vorkompilierten Headern kann ich dir jetzt nicht all zuviel sagen, da ich sie noch nie verwendet habe. Das grundprinzip besteht jedoch darin, das ein teil deines Projektes (Eben alles was im vorkompilierten Header (stdafx.h) eingeschloßen wird) Nur einmal Kompiliert und der Kompilierte Code dann Später wieder verwendet wird, anstatt ihn immer wieder neu zu Kompilieren. Das ist bei sehr großen Projekten sinnvoll, die zbs. Mehrere externe Bibliotheken mit linken. Bei mehreren Tausend Zeilen Code kann es nämlich schon mal dauern bis ein Projekt erstellt wird und man hat ja auch nicht immer lust bei jeder Kleinen Änderung erstmal Tausend Jahre zu warten bis man Testen kann...

Bei weiteren fragen gerne fragen.

LG SK

0

Ein Header ist eine Datei, die vor dem Übersetzen ins Programm kopiert wird:

main.h:

unsigned int i;

main.c:

#include "main.h"

int main() { return 0; }

So. Direkt vor dem Kompilieren, also nach dem sogenannten "Präprozessor", sieht main.c dann so aus:

unsigned int i;

int main() { return 0; }

Das erläutert nur kurz die Funktionsweise des Präprozessors. Ein sinnvoller Verwendungszweck ist etwa die Deklaration von Funktionen: Wenn eine Funktion in einer anderen Objektdatei deklariert ist, muss man beim Kompilieren, um den Compiler zu beruhigen, noch folgendes in den Quellcode schreiben:

extern int func();

Das muss man in jeder Datei machen, in der man die Funktion verwenden will. Das ist noch nicht schlimm, aber wenn es sich um sehr viele Funktionen handelt, ist es doch ziemlich umständlich, das jedes Mal hinzuschreiben. Wenn man das alles in eine Headerdatei schreibt, braucht man diese nur noch mit #include inkludieren und fertig. Beim Kompilieren ist beides genau das gleiche, aber trotzdem ist es für den Programmierer deutlich einfacher so.

Was möchtest Du wissen?