Ich frage mich also, ob diese Technik in der Praxis wirklich angewendet wird. Sollte ich es überall oder mit Vorsicht verwenden?
Natürlich wird es verwendet. Ich benutze es in meinem Projekt, in fast jeder Klasse.
Gründe für die Verwendung der PIMPL-Sprache:
Binäre Kompatibilität
Wenn Sie eine Bibliothek entwickeln, können Sie Felder hinzufügen / ändern, XImpl
ohne die Binärkompatibilität mit Ihrem Client zu beeinträchtigen (was Abstürze bedeuten würde!). Da sich das binäre Layout der X
Klasse nicht ändert, wenn Sie der Klasse neue Felder hinzufügen Ximpl
, können Sie der Bibliothek in kleineren Versionsaktualisierungen sicher neue Funktionen hinzufügen.
Natürlich können Sie auch neue öffentliche / private nicht-virtuelle Methoden hinzufügen X
/ XImpl
ohne die binäre Kompatibilität zu brechen, aber das ist auf einer Stufe mit der Standard - Header / Implementierungstechnik.
Daten verstecken
Wenn Sie eine Bibliothek entwickeln, insbesondere eine proprietäre, ist es möglicherweise wünschenswert, nicht anzugeben, welche anderen Bibliotheken / Implementierungstechniken zur Implementierung der öffentlichen Schnittstelle Ihrer Bibliothek verwendet wurden. Entweder aufgrund von Problemen mit geistigem Eigentum oder weil Sie glauben, dass Benutzer versucht sein könnten, gefährliche Annahmen über die Implementierung zu treffen, oder einfach die Kapselung durch schreckliche Casting-Tricks zu brechen. PIMPL löst / mildert das.
Kompilierungszeit
Die Kompilierungszeit wird verkürzt, da nur die Quelldatei (Implementierungsdatei) von neu erstellt werden X
muss, wenn Sie der XImpl
Klasse Felder und / oder Methoden hinzufügen / entfernen (was dem Hinzufügen privater Felder / Methoden in der Standardtechnik entspricht). In der Praxis ist dies eine übliche Operation.
Bei der Standard-Header- / Implementierungstechnik (ohne PIMPL) muss beim Hinzufügen eines neuen Felds X
jeder Client, der jemals zugewiesen wird X
(entweder auf einem Stapel oder auf einem Heap), neu kompiliert werden, da die Größe der Zuordnung angepasst werden muss. Nun, jeder Client, der niemals X zuweist, muss ebenfalls neu kompiliert werden, aber es ist nur Overhead (der resultierende Code auf der Clientseite ist der gleiche).
Darüber hinaus muss die Standardtrennung von Header und Implementierung XClient1.cpp
neu kompiliert werden, auch wenn eine private Methode X::foo()
hinzugefügt X
und X.h
geändert wurde, obwohl XClient1.cpp
diese Methode aus Kapselungsgründen möglicherweise nicht aufgerufen werden kann! Wie oben ist es reiner Overhead und hängt damit zusammen, wie echte C ++ - Build-Systeme funktionieren.
Natürlich ist keine Neukompilierung erforderlich, wenn Sie nur die Implementierung der Methoden ändern (weil Sie den Header nicht berühren), aber dies entspricht der Standard-Header- / Implementierungstechnik.
Wird diese Technik für eingebettete Systeme empfohlen (bei denen die Leistung sehr wichtig ist)?
Das hängt davon ab, wie mächtig Ihr Ziel ist. Die einzige Antwort auf diese Frage lautet jedoch: Messen und bewerten Sie, was Sie gewinnen und verlieren. Beachten Sie außerdem, dass nur der Vorteil der Kompilierungszeit gilt, wenn Sie keine Bibliothek veröffentlichen, die von Ihren Clients in eingebetteten Systemen verwendet werden soll!
struct XImpl : public X
. Das fühlt sich für mich natürlicher an. Gibt es ein anderes Problem, das ich verpasst habe?