Ein Problem in großen C ++ - Projekten kann Build-Zeiten sein. Es gibt einige Klassen in Ihrer Abhängigkeitsstruktur, an denen Sie arbeiten müssten, aber normalerweise vermeiden Sie dies, da jeder Build sehr lange dauert. Sie müssen nicht unbedingt die öffentliche Schnittstelle ändern, aber vielleicht möchten Sie die privaten Mitglieder ändern (eine Cache-Variable hinzufügen, eine private Methode extrahieren, ...). Das Problem, dem Sie gegenüberstehen, ist, dass in C ++ sogar private Member in der öffentlichen Header-Datei deklariert sind, sodass Ihr Build-System alles neu kompilieren muss.
Was machst du in dieser Situation?
Ich habe zwei Lösungen skizziert, die ich kenne, aber beide haben ihre Schattenseiten, und vielleicht gibt es eine bessere, an die ich noch nicht gedacht habe.
Das Pimpl-Muster:
Deklarieren Sie in Ihrer Headerdatei nur die öffentlichen Methoden und einen privaten Zeiger (den pimpl-Zeiger oder -Delegaten) für eine nach vorne deklarierte Implementierungsklasse.
Deklarieren Sie in Ihrer Quelle die Implementierungsklasse, leiten Sie jede öffentliche Methode Ihrer öffentlichen Klasse an den Delegaten weiter, und konstruieren Sie in jedem Konstruktor Ihrer öffentlichen Klasse eine Instanz Ihrer pimpl-Klasse.
Plus:
Minus:
John Lakos Large Scale C ++ - Softwaredesign ist ein ausgezeichnetes Buch, das die Herausforderungen beim Erstellen von großem C ++ anspricht Projekte. Die Probleme und Lösungen sind alle in der Realität begründet, und sicherlich wird das obige Problem ausführlich diskutiert. Sehr empfehlenswert.
Verwendung der Vererbung:
Deklarieren Sie in Ihrer Kopfzeile die öffentlichen Methoden als reine virtuelle Methoden und eine Factory.
Leiten Sie in Ihrer Quelle eine Implementierungsklasse von Ihrer Schnittstelle ab und implementieren Sie sie. In der Implementierung der Fabrik eine Instanz der Implementierung zurückgeben.
Plus:
Minus:
Sie können eine Forward-Deklaration für Klasse A verwenden, auf die durch Zeiger in einer anderen Klasse B verwiesen wird. Sie können dann die A-Headerdatei der Klasse in die Implementierungsdatei der Klasse B und nicht in ihre Headerdatei aufnehmen. Auf diese Weise wirken sich Änderungen an Klasse A nicht auf Quelldateien aus, die die Headerdatei der Klasse B enthalten. Jede Klasse, die auf Member der Klasse A zugreifen möchte, muss die Header-Datei der Klasse A enthalten.
Refactoring und pimpl / handle-body idiom verwenden, reine virtuelle Schnittstellen zu verwenden, um Implementierungsdetails zu verstecken scheint die beliebte Antwort zu sein. Bei der Entwicklung großer Systeme sollte man die Kompilierzeit und Entwicklerproduktivität in Betracht ziehen. Was aber, wenn Sie an einem bestehenden großen C ++ - System ohne Unit-Test-Abdeckung arbeiten? Refactoring kommt normalerweise nicht in Frage.
Was ich normalerweise mache, wenn ich nicht möchte, dass der Compiler die Welt kompiliert, nachdem ich einige gebräuchliche Header-Dateien berührt habe, ist ein Makefile / Skript zu haben, das nur die Dateien kompiliert, die ich neu kompilieren muss. Wenn ich beispielsweise einer Klasse eine nicht virtuelle private Funktion hinzufüge, muss nur die cpp-Datei der Klasse neu kompiliert werden, selbst wenn ihre Headerdatei von hundert anderen Dateien enthalten ist. Bevor ich den Tag verlasse, starte ich einen sauberen Build, um die Welt wieder aufzubauen.
Keine.
Ich sehe den Punkt bei der Verwendung eines, aber ich denke, die folgenden Argumente mildern diesen Punkt in vielen Szenarien:
Natürlich ist das am Ende eine wirtschaftliche Entscheidung. Wenn das Gewicht von "3" in Ihrem Projekt wichtig ist und aus irgendeinem Grund "6" nicht anwendbar ist, dann fahren Sie fort: Sie werden mehr von der Verwendung dieser Vorlagen gewinnen, als Sie verlieren.
Tags und Links c++ delegation pimpl-idiom