Ich sehe eine Menge Quellcode, der PImpl-Idiom in C ++ verwendet. Ich gehe davon aus, dass der Zweck darin besteht, die privaten Daten / den Typ / die Implementierung zu verbergen, damit die Abhängigkeit beseitigt und die Kompilierungszeit und das Problem mit dem Header-Einschluss verringert werden können.
Interface- / pure-abstract-Klassen in C ++ verfügen jedoch auch über diese Funktion. Sie können auch zum Ausblenden von Daten / Typ / Implementierung verwendet werden. Damit der Aufrufer beim Erstellen eines Objekts nur die Schnittstelle sieht, können wir im Header der Schnittstelle eine Factory-Methode deklarieren.
Der Vergleich ist:
Kosten :
Die Kosten für den Schnittstellenweg sind geringer, da Sie die Implementierung der Public-Wrapper-Funktion nicht einmal wiederholen
void Bar::doWork() { return m_impl->doWork(); }
müssen. Sie müssen lediglich die Signatur in der Schnittstelle definieren.Gut verstanden :
Die Schnittstellentechnologie wird von jedem C ++ - Entwickler besser verstanden.
Leistung :
Interface Way Performance nicht schlechter als PImpl Idiom, sowohl ein zusätzlicher Speicherzugriff. Ich gehe davon aus, dass die Leistung gleich ist.
Das Folgende ist der Pseudocode, um meine Frage zu veranschaulichen:
// 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;
};
Der gleiche Zweck kann über die Schnittstelle implementiert werden:
// 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();
Was ist der Sinn von PImpl?
quelle
Impl
Klasse unterbricht nicht die FunktionABI
, das Hinzufügen einer öffentlichen Funktion in der Schnittstelle wird jedoch unterbrochenABI
.unordered_set
), ohne Pimpl, muss ich#include <unordered_set>
inMyClass.h
. Mit PImpl muss ich es nur in die.cpp
Datei aufnehmen, nicht in die.h
Datei, und daher alles andere, was es beinhaltet ...Ich möchte nur Ihren Leistungspunkt ansprechen. Wenn Sie eine Schnittstelle verwenden, müssen Sie virtuelle Funktionen erstellt haben, die vom Optimierer des Compilers NICHT eingebunden werden. Die PIMPL-Funktionen können (und werden es wahrscheinlich, weil sie so kurz sind) eingebunden werden (möglicherweise mehr als einmal, wenn die IMPL-Funktion ebenfalls klein ist). Ein virtueller Funktionsaufruf kann nur optimiert werden, wenn Sie vollständige Programmanalyseoptimierungen verwenden, deren Ausführung sehr lange dauert.
Wenn Ihre PIMPL-Klasse nicht in einer leistungskritischen Weise verwendet wird, spielt dieser Punkt keine große Rolle, aber Ihre Annahme, dass die Leistung gleich ist, gilt nur in einigen Situationen, nicht in allen.
quelle
Diese Seite beantwortet Ihre Frage. Viele Leute stimmen Ihrer Behauptung zu. Die Verwendung von Pimpl bietet die folgenden Vorteile gegenüber privaten Feldern / Mitgliedern.
Das Pimpl-Idiom ist eine Optimierung zur Kompilierungszeit, eine Technik zum Aufbrechen von Abhängigkeiten. Es werden große Header-Dateien reduziert. Es reduziert Ihren Header nur auf die öffentliche Schnittstelle. Die Header-Länge ist in C ++ wichtig, wenn Sie über die Funktionsweise nachdenken. #include verkettet die Header-Datei effektiv mit der Quelldatei. Denken Sie also daran, dass vorverarbeitete C ++ - Einheiten sehr groß sein können. Die Verwendung von Pimpl kann die Kompilierzeiten verbessern.
Es gibt andere bessere Techniken zum Aufbrechen von Abhängigkeiten, bei denen das Design verbessert wird. Was bedeuten die privaten Methoden? Was ist die einzige Verantwortung? Sollten sie eine andere Klasse sein?
quelle