Methoden in Headerdateien
-
Hallihallowiegeht'sdennso?
Welche Methoden definiert ihr in Headerdateien gleich mit, welche nicht und warum?
Vielen Dank im Voraus!
-
Erstmal alles und wenn's mir zu lang wird, mach ich ne Quellcodedatei dazu.
-
der steller schrieb:
Hallihallowiegeht'sdennso?
Danke, sehr gut
Welche Methoden definiert ihr in Headerdateien gleich mit, welche nicht und warum?
Wenn überhaupt, dann nur kleine Inline-Funktionen/Methoden. Alles was größer ist, gehört in eine eigene Quelldatei, damit der Linker nicht durcheinanderkommt.
(und Templatesmüssen natürlich auch im Header definiert werden)PS: Aber zur Zeit arbiete ich nicht produktiv mit C++ - und bei SAL gelten andere Regeln.
-
CStoll schrieb:
der steller schrieb:
Hallihallowiegeht'sdennso?
Danke, sehr gut
Freut mich zu hören.
CStoll schrieb:
damit der Linker nicht durcheinanderkommt.
Wie kann er durcheinanderkommen?
-
Der Linker hat es nicht gerne, wenn er mehrere gleichnamige Objekte (z.B. mehrere Definitionen der selben Funktion, die in verschiedenen Übersetzungseinheiten eingebunden wurden) übergeben bekommt.
-
Hm.. wird das nicht eh mit
#ifndef oO #define oO #endif
verhindert?
-
Nein, diese Include-Guards verhindern nur, daß eine Header in der selben Übersetzungseinheit mehrfach eingebunden wird. Bei mehreren unabhängig übersetzten Quelldateien wird der Header trotzdem in jeder Übersetzungseinheit verwendet.
-
Ja, aber wenn die Methodenimplementierung im Klassenkörper geschieht gibt es ja trotzdem keine Konflikte.
-
Nun, deshalb meine Frage. Mein Gedankengang war Folgender: Alle Methoden müssen in Headerdateien implementiert werden können, da sonst die Nutzung von Templates irgendwie eingeschränkt wäre. Die Implementierung in Headerdateien hat Vorteile: Funktionen können "geinlined" werden, man kann eine Klasse einfach in eine Datei packen.
Die Praxis ist: Klassen werden fast nie wirklich in Headerdateien definiert.
Folge: Ich übersehe irgendwelche starken Nachteile. Welche sind das?
-
Eisflamme schrieb:
Ja, aber wenn die Methodenimplementierung im Klassenkörper geschieht gibt es ja trotzdem keine Konflikte.
Und sind damit alle inline - was man vlt nicht wirklich möchte.
Ausserdem trennst du nicht mehr was eine Klasse darstellt bzw kann und wie sie das tut.
-
Wenn du die Methoden direkt im Header definierst, müssen sie als inline definiert werden (entweder expilizit oder implizit durch Definition in der Klasse). Durch das Inlining verhinderst du die Linker-Fehler, aber ich bin mir nicht sicher, ob du dadurch nicht trotzdem mehrere Versionen der Funktion in deinem Programm hast - mit dem Ergebnis, daß die EXE größer wird.
Bei normalen Klassen ist es nicht notwendig, bei Template-Klassen ist es üblich (dort gibt es andere Gründe, daß sie direkt im Header definiert werden müssen).
-
Das soll der Nachteil sein? Dass die .exe größer wird? Das ist so ziemlich das Letzte, worüber ich mir Sorgen machen würde.
(Ich würde das Inlinen wie oben beschrieben eher als Vorteil sehen.)hmmm43 schrieb:
Ausserdem trennst du nicht mehr was eine Klasse darstellt bzw kann und wie sie das tut.
Bei der Deklaration sind ja eh auch private/protected Member sichtbar, also regelt man das dann nicht eh besser über Kommentare?
-
Schnittstelle und Implementierung zu trennen ist nicht immer so wichtig. In anderen Sprachen macht man das nicht und viele Leute haben sich im "Was würdet ihr bei C++ verbessern" gegen diese Zweiteilung ausgesprochen.
Ich stelle halt erstmal alles in die Headerdatei, weil ich die Entwicklungszeit verkürzen möchte. Oft stell ich nochmal schnell was um. Wenn es einigermaßen stabil ist, lager ich es in die Quellcodedatei aus.
Ansonsten gibt es für mich keine wirklichen Kriterien nicht-inline-Implementierungen in den Header zu stecken.
-
der steller schrieb:
Das soll der Nachteil sein? Dass die .exe größer wird? Das ist so ziemlich das Letzte, worüber ich mir Sorgen machen würde.
(Ich würde das Inlinen wie oben beschrieben eher als Vorteil sehen.)Inlining macht nur Sinn, wenn die betroffene Funktion klein genug ist, um auch Vorteile zu bieten.
hmmm43 schrieb:
Ausserdem trennst du nicht mehr was eine Klasse darstellt bzw kann und wie sie das tut.
Bei der Deklaration sind ja eh auch private/protected Member sichtbar, also regelt man das dann nicht eh besser über Kommentare?
Das wird aber schnell unübersichtlich, wenn du zwischen kiloweise Code die Methoden-Deklarationen zusammensuchen mußt (gerade wenn die Methoden umfangreicher werden).
-
CStoll schrieb:
Das wird aber schnell unübersichtlich, wenn du zwischen kiloweise Code die Methoden-Deklarationen zusammensuchen mußt
Muß man das? Muß ich eigntlich nicht.
-
der steller schrieb:
Die Implementierung in Headerdateien hat Vorteile: Funktionen können "geinlined" werden
Können sie bei gewissen Compilern in .cpp-Dateien auch, nennt sich Linkzeit-Codegenerierung.
der steller schrieb:
Folge: Ich übersehe irgendwelche starken Nachteile. Welche sind das?
- Viele Operationen benötigen vollständig definierte Typen. Zwei Klassen, die gegenseitig aufeinander zugreifen, kannst du z.B. nicht vollständig inline im Header definieren, da du sonst eine zyklische Abhängigkeit von
#include
s hast. - Durch den zusätzlichen Code in der Headerdatei ist die Kompilierzeit beim Benutzer grösser. Noch viel stärker wirkt sich das aus, wenn der Code in den Funktionsdefinitionen weitere
#include
s benötigt, die ebenfalls in den Header kommen müssen. - Jede Änderung der Implementierung erfordert eine vollständige Neukompilierung aller benutzenden Dateien.
- Du kannst keine privaten Daten in einem anonymen Namensraum verstecken, ohne sie x-fach zu duplizieren. Du kannst ausserdem keine Variablen mit externer Bindung im Header definieren.
- Falls der Compiler tatsächlich alle inline definierten Methoden
inline
macht, kann das einen negativen Einfluss auf Codegrösse und Performance haben, da der Code nicht mehr in den Cache passt. - Gewisse Leute halten es für übersichtlicher, wenn man im Header auf einen Blick die Liste aller Member sieht.
Eisflamme schrieb:
Schnittstelle und Implementierung zu trennen ist nicht immer so wichtig. In anderen Sprachen macht man das nicht
Natürlich ist die Trennung in C++ wichtig. Ganze Kapitel in Büchern wie Exceptional C++ widmen sich dem Thema, Compiletime-Abhängigkeiten zu reduzieren. Andere Sprachen haben ein Modulsystem, das ist nicht vergleichbar.
- Viele Operationen benötigen vollständig definierte Typen. Zwei Klassen, die gegenseitig aufeinander zugreifen, kannst du z.B. nicht vollständig inline im Header definieren, da du sonst eine zyklische Abhängigkeit von
-
Alles klar. Na dann zurück zur Urspungsfrage: Was packt ihr gleich mit in die Headerdatei? Nichts? Getter/Setter (kleine)? Wie umfangreich darf (eurer persönlichen Meinung nach) eine Funktion maximal sein, damit man sie noch getrost im Header definieren kann, ohne von allen Seiten Flames zu ka$$ieren?
-
Ich packe anfangs alles rein und wenn ich dann die Compilezeit optimieren will, wandern die Methoden nach und nach aus.
Es gibt keine Maximalgröße.
Flames sind mir da egal.
Ich gehe von Anfang an davon aus, daß ich die Abhängigkeiten so klein wie möglich halten will, ohne Performance zu opfern.
Ist die Funktion einfacher zu lesen als es ein die Funktion beschreibender Kommentar wäre, bleibt sie auch gerne im header.
-
der steller schrieb:
Alles klar. Na dann zurück zur Urspungsfrage: Was packt ihr gleich mit in die Headerdatei?
Templates (gezwungenermassen) und kleinere Klassen und Funktionen, die ohne zu Linken benutzbar sein sollen (meist in Verbinden mit den Templates, die ohnehin schon im Header sind und den grossen Codeteil ausmachen).
Bei normalen Klassen definiere ich sämtliche Methoden in einer .cpp-Datei.