Je vois beaucoup de code source qui utilise l'idiome PImpl en C ++. Je suppose que son objectif est de masquer les données / types / implémentations privées, de manière à pouvoir supprimer la dépendance, puis à réduire le temps de compilation et le problème d'inclusion d'en-tête.
Mais les classes d’interface / pure-abstract en C ++ ont également cette capacité, elles peuvent également être utilisées pour masquer des données / type / implémentation. Et pour que l'appelant ne voie que l'interface lors de la création d'un objet, nous pouvons déclarer une méthode factory dans l'en-tête de l'interface.
La comparaison est:
Coût :
Le coût de l'interface est moins élevé, car vous n'avez même pas besoin de répéter l'implémentation de la fonction wrapper publique
void Bar::doWork() { return m_impl->doWork(); }
, il vous suffit de définir la signature dans l'interface.Bien compris :
La technologie d'interface est mieux comprise par tous les développeurs C ++.
Performance :
Les performances de l'interface ne sont pas pires que l'idiome PImpl, un accès supplémentaire à la mémoire. Je suppose que la performance est la même.
Voici le pseudocode pour illustrer ma question:
// Forward declaration can help you avoid include BarImpl header, and those included in BarImpl header.
class BarImpl;
class Bar
{
public:
// public functions
void doWork();
private:
// You don't need to compile Bar.cpp after changing the implementation in BarImpl.cpp
BarImpl* m_impl;
};
Le même objectif peut être mis en œuvre à l'aide de l'interface:
// Bar.h
class IBar
{
public:
virtual ~IBar(){}
// public functions
virtual void doWork() = 0;
};
// to only expose the interface instead of class name to caller
IBar* createObject();
Alors, quel est l'intérêt de PImpl?
la source
Impl
classe ne cassera pas leABI
, mais ajouter une fonction publique dans une interface casseraABI
.unordered_set
), sans PImpl, je dois entrer#include <unordered_set>
dansMyClass.h
. Avec Pimpl, je ne dois inclure dans le.cpp
fichier, pas le.h
fichier, et donc tout le reste qui le comprend ...Je veux juste aborder votre point de performance. Si vous utilisez une interface, vous avez nécessairement créé des fonctions virtuelles qui NE SERONT PAS alignées par l'optimiseur du compilateur. Les fonctions PIMPL peuvent (et le seront probablement, car elles sont si courtes) en ligne (peut-être plus d'une fois si la fonction IMPL est également petite). Un appel de fonction virtuel ne peut pas être optimisé sauf si vous utilisez des optimisations d'analyse de programme complètes, qui prennent beaucoup de temps.
Si votre classe PIMPL n'est pas utilisée de manière critique en termes de performances, alors ce point importe peu, mais votre hypothèse selon laquelle les performances sont identiques ne s'applique que dans certaines situations, pas toutes.
la source
Cette page répond à votre question. Beaucoup de gens sont d'accord avec votre affirmation. L'utilisation de Pimpl présente les avantages suivants par rapport aux champs / membres privés.
Le langage Pimpl est une optimisation à la compilation, une technique de rupture de dépendance. Il réduit les fichiers d'en-tête volumineux. Cela réduit l'en-tête à l'interface publique uniquement. La longueur de l'en-tête est importante en C ++ lorsque vous réfléchissez à son fonctionnement. #include concatène efficacement le fichier d’en-tête au fichier source. Gardez donc à l’esprit que les unités C ++ pré-traitées peuvent être très volumineuses. Utiliser Pimpl peut améliorer les temps de compilation.
Il existe d'autres techniques de rupture de dépendance améliorées, qui consistent à améliorer votre conception. Que représentent les méthodes privées? Quelle est la responsabilité unique? Devraient-ils être une autre classe?
la source