2010-03-20 3 views
7

Ich habe Boost und verschiedene andere C++ - Bibliotheken. Die überwiegende Mehrheit von Boost ist in Header-Dateien implementiert.Wann, C++ - Funktion in Header-Datei

Meine Frage ist: Unter welchen Bedingungen machen Sie eine Header-only-Implementierung (wie Boost) oder auch eine .cpp-Datei?

Antwort

7

Wenn Sie eine Vorlage in einer anderen Übersetzungseinheit (d. H. Einer anderen Quelldatei) verwenden möchten, sollten Sie diese (fast immer) in der Headerdatei definieren. (Es gibt Ausnahmen, wie die Kommentare unten zeigen, aber IMHO ist dies eine gute Faustregel.)

Gleiches gilt, wenn Sie eine Inline-Funktion von einer anderen Übersetzungseinheit verwenden möchten.

Andernfalls sollten Sie die Implementierung in eine separate CPP-Datei einfügen, um Abhängigkeiten zu minimieren.

+2

Wie bei Templates ist es nicht streng zutreffend, dass Sie die (Element-) Funktionsdefinitionen in die Header-Datei einfügen müssen. Sie können die Definitionen in eine Quelldatei einfügen und eine explizite Template-Instanziierung verwenden, um bestimmte Spezialisierungen verfügbar zu machen ... –

+0

@STingRaySC Ja, ich hatte einige vage Erinnerungen an C++ Templates, die möglich sind, obwohl ich es nie selbst gemacht habe. Ich habe jedoch versucht, eine Faustregel zu geben, die für Anfänger und fast immer anwendbar ist. In die speziellen Fälle zu gehen ist für die Experten (von denen ich nicht eins bin :-) –

+0

Und Sie müssen nicht Vorlage Implementierungen in der Header-Datei bereitstellen, wenn Ihr Compiler 'export' unterstützt – smerlin

3

Bei diesem Problem geht es hauptsächlich darum zu verstehen, wie C++ - Kompilierungseinheiten funktionieren. Dinge in Header-Dateien werden grundsätzlich in den Quellcode einer ganzen Reihe von Compilation-Units eingefügt durch #include Anweisungen. Jede Kompilierungseinheit wird in eine Objektdatei kompiliert, die Objektdateien werden verknüpft und Sie erhalten Konflikte, weil das Zeug überall repliziert wird.

Die Ausnahmen sind Dinge, die (zumindest historisch) nicht in die Objektdatei gehen, weil der Compiler direkt mit ihnen umgeht (zB Inline-Funktionen) und Dinge, die nicht in einer Einheit kompiliert werden können ein anderer, weil sie nicht vollständig definiert sind (Vorlagen). Template-Funktionen oft werden identisch in mehreren Kompilierungseinheiten instanziiert, und der Linker verfügt über spezielle Smart, um die Duplikate zu verwerfen.

Dies bedeutet, dass die Trennung von Schnittstelle und Implementierung in Header und Textdateien nicht so sauber ist. Ada hat eine viel sauberere Trennung - aber einen komplexeren Build-Prozess, um IIRC zu kompensieren. Java ließ einfach die separaten Dateien für die Schnittstelle und die Implementierung fallen.

Linker haben im Laufe der Jahre viel mehr entwickelt und einige der Arbeit des Compilers übernommen, und eine Menge dieser Erklärung ist heutzutage einfach falsch, aber die grundlegenden Muster bleiben. Template-Funktionen und Inline-Funktionen können (und müssen oft) in den Header eingefügt werden, zusammen mit all Ihren gemeinsamen Deklarationen, die nicht direkt generieren. Normale Funktionsdefinitionen sollten sich nicht in einer Header-Datei befinden.

+0

Eigentlich sind Linker nicht so schlau über "Schablonen" -Instanzen. Sie werden grundsätzlich das erste treffen, auf das sie stoßen, und sich auf ** ODR ** (eine Definitionsregel) verlassen. Kann zu einem schwer zu findenden Fehler führen, wenn nur ein Teil der 'Foo ' Instanziierungen eine Spezialisierung verwendet! –

Verwandte Themen