Header Aufteilung
-
Hi,
ich möchte mich etwas näher mit der Spieleprogrammierung beschäftigen.
Die Grundlagen von C++ sind mir soweit bekannt.Allerdings habe ich eine Frage zur Aufteilung der Header-Dateien:
Ich plane zur Übung eine Art kleine Grafik-Engine in Form einer statischen Bibliothek zu machen.
Kann ich eine einzige große Header-Datei, in der alle anderen Header-Dateien inkludiert werden, erstellen? So dass ich in allen Quellcode-Dateien sowie in den Projekten, die diese statische Bibliothek benutzen immer nur diese eine Header-Datei einbinden muss?
Für kleinere Projekte mag das sicher gehn, aber wie sieht es später mit hunderten Klassen und hunderten Dateien aus?Gruß
-
Das macht man nicht, weil du immer nur das inkludieren sollst, was wirklich gebraucht wird. Mit Sicherheit braucht nicht jede cpp oder hpp File all deine Header.
-
Klar kannst du das.
@out
"man" macht das nicht?
Klar macht "man" das. Die meisten Libraries die ich kenne haben solche Header Files.
Irre praktisch.
Und wer's schnell haben will muss die ja nicht verwenden - kann ja immer noch alles einzeln inkludieren.
-
Es besteht ein Unterschied, ob man solch einen Header zur Verwendung nach außen hin anbietet oder ob man so etwas intern benutzt. Erfahrungsgemäß haben Leute, die so etwas intern benutzen wollen, meistens nicht so recht den Durchblick, was in solch eine Headersammlung warum rein gehört und was nicht, und packen einfach alles rein. Was dann ganz schnell schief geht, sobald man gegenseitige Abhängigkeiten hat (und die hat man in jedem Projekt, bei dem man eine nennenswerte Anzahl Headerdateien hat).
-
Oha, ja.
Dass "in allen Quellcode-Dateien sowie in den Projekten" natürlich auch die Source-Files der Library selbst mit einschliesst hab' ich ganz sorgfältig übersehen
Das ist in der Tat nicht sehr üblich, und vermutlich auch nicht sehr schlau.
In Kombination mit Precompiled-Headers kann man damit zwar oft die Rebuild-All Dauer halbwegs gut reduzieren, aber dafür macht man während des Entwickelns bei jeder kleinen Änderung effektiv ein Rebuild-All. Was dann meist weniger Spass macht.SeppJ schrieb:
Erfahrungsgemäß haben Leute, die so etwas intern benutzen wollen, meistens nicht so recht den Durchblick, was in solch eine Headersammlung warum rein gehört und was nicht, und packen einfach alles rein. Was dann ganz schnell schief geht, sobald man gegenseitige Abhängigkeiten hat (und die hat man in jedem Projekt, bei dem man eine nennenswerte Anzahl Headerdateien hat).
Versteh ich jetzt nicht ganz warum das zu einem Problem wegen gegenseitiger Abhängigkeiten führen sollte.
Gegenseitige Abhängigkeiten muss man sowieso über Forward-Declarations lösen.
Und dann ist es auch egal wenn man ein grosses "inkludiere mir mal eben alles" File hat, das man in jedem Source-File inkludiert.Oder übersehe ich jetzt 'was?
-
hustbaer schrieb:
Versteh ich jetzt nicht ganz warum das zu einem Problem wegen gegenseitiger Abhängigkeiten führen sollte.
Gegenseitige Abhängigkeiten muss man sowieso über Forward-Declarations lösen.
Und dann ist es auch egal wenn man ein grosses "inkludiere mir mal eben alles" File hat, das man in jedem Source-File inkludiert.Oder übersehe ich jetzt 'was?
"Gegenseitig" ging etwas zu weit. Überhaupt Abhängigkeiten wäre passender. Typischerweise (so etwas kommt hier im Forum ja durchaus öfters vor) geht das so vor sich:
A.h benötigt B.h. Also steht in A.h auch brav#include "B.h". In beiden steht natürlich auch#include "superheader.h". Und im Superheader steht natürlich#include "A.h" #include "B.h"Und dann wundern sie sich, warum in A.h die Deklarationen aus B.h nicht gefunden werden.
(Falls mein Beispiel zufällig so gewählt sein sollte, dass es passt: Ich wollte jetzt nicht alle Präprozessoranweisungen im Kopf auflösen
. Jedenfalls ist der ganze Vorgang hochgradig störanfällig gegenüber Veränderungen der include-Reihenfolge. Welcher Header am Ende zuerst eingebunden wird ist nur schwer vorhersehbar.)
-
Einen Header zu machen, der alle anderen Header includiert macht nur dann Sinn, wenn man seine Header nicht mehr verändert. Sobald du nämlich einen Header änderst, müssen all deine Cpp-Dateien, welche diesen Header includieren neu kompiliert werden.
Falls du Visual Studio verwendest gibt's da noch Vorkompilierte Header.
Vorkompilierte Header sind aber auch nur dazu gut, den Kompiler die Header nicht neu kompilieren lassen zu müssen, falls Änderungen in einer Cpp vorgenommen wurden, welche Header aus der Vorkompilierten Header-Datei includieren. Diese Funktion ist also auch nur für Header geeignet, welche nicht mehr verändert werden.
-
@SeppJ
Ah, OK, ja, verstanden
In
A.hundB.hdarf natürlich nicht#include "superheader.h"stehen.
Sondern da steht#include "basisheader.h", und#include "superheader.h"steht nur in allen Sourcefiles.
-
Mr. schrieb:
Diese Funktion ist also auch nur für Header geeignet, welche nicht mehr verändert werden.
Nein.
-
@hustbaer: care to elaborate?
Wann ist es sinnvoll Header, die sich noch in der Entwicklung befinden, in den precompiled header zu packen?
-
Wenn es Header sind die sowieso so-gut-wie überall inkludiert werden müssen löst das effektiv sowieso einen kompletten Rebuild aus. Dann kann man die genau so gut gleich mit ins PCH File reintun. Speziell wenn sie richtig gross sind und viel Standard/Thirdparty Zeugs inkludieren.
-
Na okay, darüber zu streiten ist wohl Korinthenkackerei. Bei mir sind Header, die sich in der Entwicklung befinden noch nicht überall in Verwendung. Andererseits entwickle ich Subsysteme/Header usw., also Zeug, das dann mal überall verwendet werden soll, sowieso meist in separaten Projekten.
Wir wissen ja alle was die Folgen sind, so oder so, denke ich