Warum sollte man die header erst in der cpp-datei inkludieren?
-
Welche Begründung gibt es dafür? Ich hab bisher einfach alles in die Header gepackt... ?
-
Die class.cpp wird extra compiliert, dabei brauchst du natürlich dass es syntaktisch korrekt ist die Klassendefinition in der class.h. Damit deine Klasse in der main.cpp bekannt ist musst du nur die class.h einbinden, nicht die class.cpp da die Implementierung der Klasse dann dazu gelinkt wird.
-
Du kannst auch viele Headerdateien in eine Headerdatei einbinden. Aber wenn es nicht nötig ist, macht man das nich, da dann schneller kompiliert werden kann, wenn du ma ein paar Zeilen änderst.
Oder du machst es stellenweise so:
// yourCLASS.h class label; class yourCLASS { ... label itsLabel; ... }; // yourCLASS.cpp #include "label.h"statt
// yourCLASS.h #include "label.h" class yourCLASS { ... label itsLabel; ... }; // yourCLASS.cpp ...MfG
-
Ich glaub so ganz die Antwort auf meine Frage war das nicht? Ich meine ich habs bisher so gemacht
// Irgendeine Header.h #include <map> #include <list> #include <queue> #include <string> #include <fstream> using namespace std;jetzt haben mir 3 Leute erzählt man packt diese includes, außer man braucht sie natürlich schon für Klassenvariablen, in die zugehörige cpp datei.
Warum?
-
Erstmal zu dem using (...):
Man pack _NIE_ ein using in eine Header-Datei. Das hat den einfach Grund dass wenn man dann die Header-Datei einbindet man das using (...) übernimmt, das will man nicht.
-
ich weiß warum man das nicht macht aber die eigentliche Frage ist immer noch nicht beantwortet

-
damit es schneller kompiliert
-
?! Klingt komisch, begründung?
-
// Irgendeine Header.h
#include <map>
#include <list>
#include <queue>
#include <string>
#include <fstream>
using namespace std;und schon wieder:
- niemals "using namespace ..." in Header-Dateien!!!Zum eigentlichen Topic:
Da dieser Header auch in anderen Dateien includiert werden könnte, würden jedesmal die STL-Header eingebunden, was bei großen Projekten ziemlich viel Kompilierzeit kosten kann. Falls bestimmte Datentypen (fast) überall im gesamten Projekt benutzt werden, kann man sie in sog. vorkomplierte Header-Dateien packen, bzw. eine eigene "project.h" anlegen, die dann von allen Cpp-Dateien includiert wird.Bei den includes könnte es nachher auch zu Reihenfolge-Probleme kommen, falls eine Datei dann nicht mal die STL einbindet, sie aber benutzt. Falls dann nicht die Header-Datei eingebunden wird, kommt es dann zu Kompilierfehlern, also am besten von Anfang an sauber strukturieren und nur das einbinden, das auch benötigt wird.
Aber auch der Kommentar von "Saiyaman" ist ok, falls eine Klasse nur als Pointer oder Referenz in der eigenen Header-Datei auftaucht.
Da die STL auf templates basiert, müssen leider immer die ganzen Definitionen eingebunden werden, d.h. man kann leider NICHT
class std::vector<int>; class X { std::vector<int> vInts; };schreiben, aber nur für diesen Fall sollten die STL-Header in der eigenen Header-Datei includiert werden.
Ich hoffe, du verstehst jetzt mehr -)
P.S. Ich nehme an, du hast noch nicht Projekte von mehreren zehn oder sogar hundert Dateien erzeugt, oder?
-
Naja aber die Header die man für das Interface braucht müssen schon in die Header-Datei. Die anderen können in die Implementierung wenn sie nur hier genutzt werden.
Also z.b.:
// unsinniges beispiel --> /*** foo.h ***/ #include <vector> struct foo { void ausgabe(std::vector<int> bla); }; /*** foo.cpp ***/ #include "./foo.h" #include <iostream> #include <iterator> #include <algorithm> void foo::ausgabe(std::vector<int> bla) { std::copy(bla.begin(), bla.end(), std::ostream_iterator<int>(std::cout, ",")); }
-
Leute, helft oder lasst es.
Punkt 1.) Ich habe nur ein Beispiel gegeben, ich habe letztens erst einen Vortrag über Namespaces gehalten und weiß das man die anderen Wege benutzen sollte anstatt die using namespace X direktive.
Punkt 2.)
Ich habe bereits geschrieben das man natürlich die Header in der Header lassen sollte, die in der Klasse verwendet werden, sonst geht's nicht.Punkt 3.)
Th schrieb:
[...]
Zum eigentlichen Topic:
Da dieser Header auch in anderen Dateien includiert werden könnte, würden jedesmal die STL-Header eingebunden, was bei großen Projekten ziemlich viel Kompilierzeit kosten kann. Falls bestimmte Datentypen (fast) überall im gesamten Projekt benutzt werden, kann man sie in sog. vorkomplierte Header-Dateien packen, bzw. eine eigene "project.h" anlegen, die dann von allen Cpp-Dateien includiert wird.
[...]So so, werden sie das? Ich dachte das wird durch ifndef verhindert? Sprich einmal "reinkopiert", danach ist gut.
Ich will eine einfache Antwort und eure Antworten sind erstens keine und zweitens klingen sie nicht schlüssig.

-
Im übrigen: falls du in einer Headerdatei eine Klasse erwänst, aber nicht benutzt (also z.B. ein Datenelement von dem Typ hast, aber nicht die Klassenmethoden benutzt), dann sollte man die zugehörige Headerdatei in der eigenen Headerdatei garnicht erst einbinden.
Ferner verweise ich wiedermal gerne auf mein Lieblingsbuch: Scott Meyers' "effective C++" (auf deutsch: "effektiv C++ programmieren") bietet auch zu dem Thema Kompilationsabhängigkeiten und includes ein eigenes Kapitel und ist auf jedenfall das Geld wert (kostet momentan afaik ca. 17 Euro)was die unterscheidung von includes in header oder .cpp angeht:
meistenteils werden mit den Includes neue Klassenschnittschtellen geladen, die mit der selbsterstellten Klassenschnittstelle nichts zu tun haben (sollten). Die Fremdheader sind also Implementationsdetails, die in einer headerdatei nichts verloren haben. Man stelle sich vor, man hat in der neuen KLasse ein Datenmember vom typ T. Als vernünftiger Programmierer macht man das Datenmember private und stellt ggfs. get/set-Methoden zur Verfügung. Wie die Implementierung meiner KLassenmethoden die Methoden von T benutzt, geht den klienten nichts an, er muss höchstens wissen, dass es die Klasse T gibt. Deshalb reicht eine einfache Deklaration in der Headerdatei:class T;Mehr muss der Klient nicht wissen. Sollte er die get/setter-Methoden benutzen wollen, so muss er sich selbst darum kümmern, die Schnittstelle von T zu includieren. Das ist das Prinzip der kapselung udn des information hiding.
Folgendes Szenario:
Ich benutze die Klasse T nur, um intern meine Daten zu verwalten. Der klient braucht sie eigentlich nicht. Trotzdem hab ich in meine MyClass.hpp ein "#include T.hpp" hineingeschrieben, statt der oben gezeigten einfachen Deklaration. Ich habe jetzt festgestellt, dass ich meine Klasse T noch erweitern möchte, und schreibe sie mitsamt header etwas um. Im normalfall htte ich nur T und MyClass neu kompilieren müssen, weil ja MyClass.hpp unverändert ist und alles, was davon abhängt also auch. weil ich aber T.hpp inkludiert hab und die sich geändert hat, muss alles, was direkt oder indirekt MyClass.hpp inkludiert, auch neu kompiliert werden. Und da ich ja bei der T.hpp mit dem include so großzügig war, war ich das andernorts mit sicherheit auch, und muss die ganze Welt neu kompilieren. Viel Spaß...
-
unwissenderwissbegieriger schrieb:
So so, werden sie das? Ich dachte das wird durch ifndef verhindert? Sprich einmal "reinkopiert", danach ist gut.
Es geht hier um mehrere Kompilierungseinheiten, da wird jedes mal neu "reinkopiert". Und dass das nicht passiert macht man es in die .cpp. So wird es nur in die eine Einheut "reinkopiert"...
Hört sich lustig an... "reinkopiert"
-
Das klingt für mich aber nicht wirklich plausibel, bisher war das bei allen Projekte so die ich mir angeschaut habe
quake, blood, jagged alliance 2 usw.
Soll das der einzige Grund sein?
-
Also dann machs eben nicht so.
Du willst nicht geholfen werden.
-
unwissender: weitere gründe siehe mein editierter post
-
unwissender324 schrieb:
Das klingt für mich aber nicht wirklich plausibel, bisher war das bei allen Projekte so die ich mir angeschaut habe
quake, blood, jagged alliance 2 usw.
Soll das der einzige Grund sein?
Das die Unsitte einen "Ich include hier alles was ich brauche"-Header zu benutzen weit verbreitet ist, ist kein gegenbeweis. Es gibt viele weit verbreitete Angewohnheiten die trotzdem nicht gut sind.

Selbst mit precompiled Headerfiles sind die Buildzeiten durchaus teilweise deutlich länger, als wenn jede Komponente nur includet was sie benötigt. Grosse Firmen kompensieren die durch Faulheit entstehenden Buildzeiten manchmal mit parallelisierten Builds im Netz, so das es dort nicht so auffällt, aber die Option hat man selber eher nicht (wenn man nicht über einen Maschienenpark verfügt). In einem Großprojekt in dem ich eine Zeitlang war, hat das einiges gebracht. (Die Buildzeiten waren da allerdings auch jenseits dessen was man normalerweise so erlebt.)
Zudem kann man bei sorgsamer Pflege der Includes auch auf einen Blick sehen, was eine Komponente so alles benötigt. Das ist vor allem bei non-standard-Includes wie third-party-Libs eine schöne zusätzliche Dokumentation wenn man das Projekt pflegen und neuen Gegebenheiten anpassen muß.
Tauchen in diesem Wollmilchsau-Header dann noch so Sachen wie eigene tools in einer Art utility.h auf, so baut sich das system jedesmal den Oberwolf, wenn man darin was ändert, selbst wenn das nur selten gebraucht wird.
-
unwissenderwissbegieriger schrieb:
Ich glaub so ganz die Antwort auf meine Frage war das nicht? Ich meine ich habs bisher so gemacht
// Irgendeine Header.h #include <map> #include <list> #include <queue> #include <string> #include <fstream> using namespace std;jetzt haben mir 3 Leute erzählt man packt diese includes, außer man braucht sie natürlich schon für Klassenvariablen, in die zugehörige cpp datei.
Warum?
Genau das hab ich dir doch in meinem Post erklärt

MfG

-
unwissenderwissbegieriger == Troll
-
Nö, die einzigehalbwegs nachvollziehbare Erklärung war IMHO die von pumuckl. Den Rest kann man doch nicht verstehen, wenn man den Grund noch nicht weiß.
-
Michael E. schrieb:
Nö, die einzigehalbwegs nachvollziehbare Erklärung war IMHO die von pumuckl. Den Rest kann man doch nicht verstehen, wenn man den Grund noch nicht weiß.
Danke, ich bin nämlich definitiv kein Troll.