Design von C ++ - Header-Dateien: Genau wie beim Definieren einer API?

8

Ich bin ein bisschen neu in der groß angelegten Softwareentwicklung in C ++ und habe mich auf der Design-Seite gefragt.

Ich habe diese Frage gelesen und dachte, dass C ++ - Header-Dateien , sobald wir konstante Definitionen und andere triviale Dinge überwunden haben, insgesamt nur API-Definitionen sind :

Sie definieren, was andere Programmierer (oder Sie selbst aus anderen Modulen) verwenden können (Klassen, öffentliche Funktionen), aber es sollte keine private Klasse oder Funktion darin definiert werden. Es ist, als ob die Header-Datei die Abstraktionen (Schnittstellen ...) definiert und die Quelldatei sie implementiert. Sobald die Quelldatei kompiliert ist, werden die Implementierungsdetails ausgeblendet und bleiben die öffentlich verfügbaren Header, die definieren, was das Modul tun kann.

Ich war der Meinung, dass diese Ansicht der Trennung von Header- und Quelldateien viel einfacher zu verstehen und zu befolgen war als die üblichen Erklärungen, da man sich nur vorstellen kann, dass es sich XXXum öffentlich verfügbares API-Material handelt oder dass es sich um ein Wurstherstellungsdetail handelt, das in einem versteckt ist unbekannte Quelldatei? "

Ist mein mentales Modell von Header-Dateien ungefähr korrekt? Was habe ich verpasst ?

Jiby
quelle
Schauen Sie sich auch UML für ein System an, das zum Entwerfen von Software erstellt wurde - seine Klassen zeigen API-Methoden und
-Daten
Oh glauben Sie mir, ich weiß über UML! = p Es ist nur die C ++ - Art zu denken, dass ich Probleme habe, meinen Kopf herumzuwickeln. Ich "komme aus der Python-Welt", mit all den Vorurteilen zu denken "Warum sollte eine Sprache Header-Dateien benötigen?" =)
Jiby

Antworten:

10

Es ist kein schlechtes mentales Modell, um es als Leitfaden zu verwenden, aber leider verbinden C ++ - Header aus historischen / technischen Gründen Schnittstelle und Implementierung auf eine Weise, die dieses einfache mentale Modell nicht vollständig erfasst.

Um gute Entscheidungen zum physischen Design zu treffen, wenn die Dinge etwas komplexer werden, ist es im Allgemeinen erforderlich, die Funktionsweise von Headern in C ++ auf einer detaillierteren Ebene zu verstehen.

Ein Beispiel: In Ihrer API-Ansicht sollte eine Header-Datei nicht die Definition einer privaten Implementierungsklasse enthalten. In der Praxis werden solche Klassendefinitionen jedoch häufig in einer Header-Datei angezeigt, da der Compiler ihre Größe kennen muss, wenn sie in öffentlichen Klassen enthalten sind. Es gibt Techniken, um diese Art von Abhängigkeit zu überwinden, aber sie verursachen im Allgemeinen Kosten in Bezug auf Codekomplexität, Leistung oder beides. Um zu verstehen, wann es angemessen ist, eine dieser Techniken zu verwenden, müssen Sie besser wissen, wie Header in C ++ funktionieren.

mattnewport
quelle
Ich habe über die Vorwärtsdefinitionen privater Klassen nachgedacht: Können wir betrügen, indem wir sie in eine separate "versteckte" Header-Datei einfügen und sie einschließen? Auf diese Weise würden Sie den "einfachen API-Header" und einen "schmutzigen privaten Trick" beibehalten. Ich bin mir nicht sicher, ob es viel Gutes bringen würde.
Jiby
@Jiby Ein separater "Detail" -Header ist eine weit verbreitete Methode, um Details der privaten Implementierung aufzuteilen. Ja, das kann ein guter Ansatz sein. Es ist auch durchaus üblich, Implementierungsdetails in einem verschachtelten detailNamespace abzulegen, damit sie den Namespace der Hauptbibliothek nicht verschmutzen und klarstellen, dass sie nicht direkt verwendet werden sollen.
Mattnewport
3

Es gibt kaum einen Unterschied zwischen einer Header-Datei und einer Schnittstelle, wie sie von anderen Sprachen für den Hauptteil verwendet wird. Natürlich gibt es Unterschiede in der Implementierung darin, dass der Header auch private Informationen enthält, aber im Grunde werden sie verwendet, um die Funktionen zu beschreiben, die die Klasse oder das Modul bereitstellen wird.

In gewisser Weise ist es auch ein mentales Modell von Datenstrukturen in Kombination mit der API, sodass es nützlicher sein kann, wenn Sie das von Ihnen beschriebene anfängliche Design ausführen.

Idealerweise enthält ein Header, der eine API definiert, nur die reine Schnittstelle. Da C ++ jedoch keinen ABI hat, spielt dies keine Rolle. Wenn Sie ein übergeordnetes System erstellen, das eine reine Client-Schnittstelle bietet, verwenden Sie einen anderen Mechanismus wie eine IDL oder WSDL, um dies trotzdem zu definieren.

gbjbaanb
quelle
2
Siehe auch: Zeiger auf die Implementierung
rwong
-1

Die Header-Datei als reine Schnittstelle funktioniert mehr oder weniger gut mit Klassen. Sobald Vorlagen angezeigt werden, funktioniert dieses Modell überhaupt nicht mehr. Vorlagen sind nicht kompilierbar und die gesamte Vorlagenimplementierung muss im Header angezeigt werden.

user58697
quelle
Können wir herumschummeln, indem wir vorlagenbezogenen Code in einen separaten Header schreiben und ihn einschließen?
Jiby