2010-12-25 3 views

Antwort

7

Einige Gründe:

(1) Incremental Bauzeiten

Wenn Projekte größer werden, die Verwaltung der Aufbauzeit vor allem für C++ Projekte problematisch ist. Gebäude 1 oder 5 Minuten nach einer kleinen Änderung macht einen großen Unterschied. Dies wird durch die meisten Änderungen in großen Projekten betont, die klein sind und erfordern eine Menge Tests. Fügen Sie dazu einen Versuch von TDD und Refactoring hinzu, und Sie sind eine tote Schnecke mit sizilianischen Schuhen.

Die Aufteilung in Header und Body und das Verschieben in libs verbessert die inkrementellen Build-Zeiten enorm.

(2) Statiken
Für viele Dinge, die Sie eine einzelne Instanz eines Typs benötigen, dh

// .cpp 
static Foo foo; 

Es gibt keine Möglichkeit (die ich bin mir dessen bewusst) ermöglicht dies in einem Header- nur Projekt. Compiler-spezifische Lösungen sind begrenzt, z. __declspec(selectany) in MSVC ist auf POD-Typen beschränkt.

(3) Implementierung versteckt
CPP/.h Trennung ist der einzige Weg, um eindeutig eine öffentliche Schnittstelle von Implementierungsdetails trennen. Sie können Klassenmitglieder in einen Abschnitt private werfen, aber das funktioniert nicht für andere Entitäten. (Sogar die Header/Body-Trennung ist undicht, es sei denn, Sie fügen zusätzliche Techniken wie PIMPL hinzu, also ist dieses Argument ein bisschen schwach IMO, aber wiederum würde ich in einem großen Projekt diese effiziente, wenn auch unvollkommene Methode vermissen).


Große Frage, sowieso - Sie haben erkannt, dass es etwas in Konflikt geraten mit dem C/C++ Modell zu bauen, das ich ein altes Relikt der schrecklichen Auswirkungen berücksichtigen.

Sie sollten versuchen, wie weit Sie ein "nur Kopf" -Modell schieben können (oder zumindest "fast nur Kopfzeilen", um Statik zu ermöglichen). Sie könnten ziemlich weit kommen - es wäre auch interessant von Leuten zu hören, die es versucht haben.

Es könnte einen Versuch wert sein, statische Bibliotheken zu verwenden, um Implementierungen zu trennen und zu kapseln, und ansonsten den gesamten Code in den Headern zu behalten. Ich kann ein paar Probleme damit sehen, aber es ist nicht so, dass unser aktueller Modus operandi problemlos ist.

+4

+1 für den Aufruf von C/C++ Build/Link-Modell, das wirklich ziemlich düster ist –

2

Header-Dateien (.h) dienen dazu, die Schnittstelle zu definieren, damit Ihre Klassen und Ihr Code in anderen Übersetzungseinheiten verwendet werden können. Wenn Sie die Implementierung in die .h-Datei einfügen, erhalten Sie mehrere Kopien desselben Codes, die in jede Übersetzungseinheit kompiliert werden, die diese .h-Datei enthält. Das vereitelt den Punkt, den Code in kleine Teile zu teilen, die isoliert studiert und entwickelt werden können.

+0

Ich denke, es könnte noch getan werden, können Sie die öffentliche Schnittstelle in die Header, die die "Implementierungsheader" enthalten, wie Boost mit den "Details" Unterordner setzen. Ohne starke Verwendung von Schnittstellen stimmt die .h/.cpp-Trennung sowieso nicht sehr gut mit der Schnittstelle/Implementierungstrennung überein. – peterchen

3

Sie könnte setzen Sie Ihren gesamten Code in .h-Dateien. Entgegen der landläufigen Meinung wird dies den Code in Ihren OBJ-Dateien nicht kopieren. Moderne Compiler sind viel schlauer als das.

Compilation ist etwas ein Problem. Wenn Sie 20 .h Dateien haben, die alle in main.cpp enthalten sind, dauert das Kompilieren von main.cpp eine Weile. Und es wird jedes Mal, wenn sich eine Ihrer Include-Dateien ändert, neu kompiliert, einschließlich aller 20 Dateien Ihrer Implementierung .h.

Dann gibt es Stil. Es sieht einfach falsch für mich aus. Aber das ist eine Frage der Präferenz.

Dann gibt es Referenzen. Wenn ClassA ClassB verwendet und ClassB ClassA verwendet, welchen enthält du zuerst?

+0

Ich sehe nicht, wo moderne Compiler hinein kommen. Sobald Sie mehrere Übersetzungseinheiten haben, die Header-Dateien mit Implementierung enthalten, kopieren Sie Code in die Objektdateien. Ja, in der Theorie könnte diese Duplizierung entfernt werden, aber das müsste vom Linker und nicht vom Compiler gemacht werden. –

+0

Ihre Annahme über Linker und Compiler-Rollen ist ziemlich veraltet. Die Erzeugung von Link-Zeit-Code wird seit einem Jahrzehnt weitverbreitet verwendet. Eine schlampige Art, das zu sagen, wäre, dass der Compiler mit LTCG nur ein schicker Präprozessor ist: Die .obj-Dateien enthalten eigentlich keinen Maschinencode. Und doppelte (und unnötige, etc, usw.) Code ist eine Gegebenheit. – martona

+0

klingt alles sehr clever - nur schade, dass es nötig ist, um mit dem veralteten Build-Modell von C/C++ fertig zu werden! –

Verwandte Themen