Alors, je me demande si cette technique est vraiment utilisée dans la pratique? Dois-je l'utiliser partout ou avec prudence?
Bien sûr, il est utilisé. Je l'utilise dans mon projet, dans presque toutes les classes.
Raisons d'utiliser l'idiome PIMPL:
Compatibilité binaire
Lorsque vous développez une bibliothèque, vous pouvez ajouter / modifier des champs à XImpl
sans interrompre la compatibilité binaire avec votre client (ce qui signifierait des plantages!). Étant donné que la disposition binaire de la X
classe ne change pas lorsque vous ajoutez de nouveaux champs à la Ximpl
classe, il est prudent d'ajouter de nouvelles fonctionnalités à la bibliothèque dans les mises à jour de versions mineures.
Bien sûr, vous pouvez également ajouter de nouvelles méthodes non virtuelles publiques / privées à X
/ XImpl
sans rompre la compatibilité binaire, mais c'est à égalité avec la technique d'en-tête / d'implémentation standard.
Masquage des données
Si vous développez une bibliothèque, en particulier une bibliothèque propriétaire, il peut être souhaitable de ne pas divulguer quelles autres bibliothèques / techniques d'implémentation ont été utilisées pour implémenter l'interface publique de votre bibliothèque. Soit à cause de problèmes de propriété intellectuelle, soit parce que vous pensez que les utilisateurs pourraient être tentés de prendre des hypothèses dangereuses sur l'implémentation ou simplement casser l'encapsulation en utilisant de terribles astuces de casting. PIMPL résout / atténue cela.
Temps de compilation
Le temps de compilation est réduit, car seul le fichier source (implémentation) de X
doit être reconstruit lorsque vous ajoutez / supprimez des champs et / ou des méthodes auXImpl
classe (ce qui correspond à l'ajout de champs / méthodes privés dans la technique standard). En pratique, c'est une opération courante.
Avec la technique d'en-tête / d'implémentation standard (sans PIMPL), lorsque vous ajoutez un nouveau champ à X
, chaque client qui alloue X
(soit sur pile, soit sur tas) doit être recompilé, car il doit ajuster la taille de l'allocation. Eh bien, chaque client qui n'alloue jamais X doit également être recompilé, mais c'est juste une surcharge (le code résultant du côté client sera le même).
De plus, avec la séparation standard en-tête / implémentation, il XClient1.cpp
faut recompiler même lorsqu'une méthode privée a X::foo()
été ajoutée X
et X.h
modifiée, même si elle XClient1.cpp
ne peut pas appeler cette méthode pour des raisons d'encapsulation! Comme ci-dessus, il s'agit d'une surcharge pure et liée au fonctionnement des systèmes de construction C ++ réels.
Bien sûr, la recompilation n'est pas nécessaire lorsque vous modifiez simplement l'implémentation des méthodes (car vous ne touchez pas l'en-tête), mais c'est à égalité avec la technique d'en-tête / d'implémentation standard.
Cette technique est-elle recommandée pour être utilisée dans les systèmes embarqués (où les performances sont très importantes)?
Cela dépend de la puissance de votre cible. Cependant, la seule réponse à cette question est: mesurez et évaluez ce que vous gagnez et perdez. De plus, sachez que si vous ne publiez pas une bibliothèque destinée à être utilisée dans des systèmes embarqués par vos clients, seul l'avantage du temps de compilation s'applique!
struct XImpl : public X
. Cela me semble plus naturel. Y a-t-il un autre problème que j'ai manqué?