Warum sollte die Redewendung „PIMPL“ verwendet werden? [duplicate]

Lesezeit: 9 Minuten

Warum sollte die Redewendung „PIMPL verwendet werden duplicate
JeffV

Hintergrund:

Die PIMPL-Idiom (Pointer to IMPLementation) ist eine Technik zum Verbergen der Implementierung, bei der eine öffentliche Klasse eine Struktur oder Klasse umschließt, die außerhalb der Bibliothek, zu der die öffentliche Klasse gehört, nicht sichtbar ist.

Dies verbirgt interne Implementierungsdetails und Daten vor dem Benutzer der Bibliothek.

Warum sollten Sie bei der Implementierung dieses Idioms die öffentlichen Methoden in der Pimpl-Klasse und nicht in der öffentlichen Klasse platzieren, da die Methodenimplementierungen der öffentlichen Klassen in die Bibliothek kompiliert würden und der Benutzer nur die Header-Datei hat?

Zur Veranschaulichung setzt dieser Code die Purr() Implementierung auf der impl-Klasse und umschließt sie ebenfalls.

Warum nicht Purr direkt in der öffentlichen Klasse implementieren?

// header file:
class Cat {
    private:
        class CatImpl;  // Not defined here
        CatImpl *cat_;  // Handle

    public:
        Cat();            // Constructor
        ~Cat();           // Destructor
        // Other operations...
        Purr();
};


// CPP file:
#include "cat.h"

class Cat::CatImpl {
    Purr();
...     // The actual implementation can be anything
};

Cat::Cat() {
    cat_ = new CatImpl;
}

Cat::~Cat() {
    delete cat_;
}

Cat::Purr(){ cat_->Purr(); }
CatImpl::Purr(){
   printf("purrrrrr");
}

  • Weil das PIMP-Idiom vermieden werden sollte?..

    – mlvljr

    7. Oktober 2010 um 21:31 Uhr

  • Ausgezeichnete Antwort, und ich fand, dass dieser Link auch umfassende Informationen enthält: marcmutz.wordpress.com/translated-articles/pimp-my-pimpl

    – zhanxw

    18. Februar 2013 um 14:24 Uhr

  • Wenn Sie dem Wartungscoder, der nach Ihnen kommt, einen Gefallen tun möchten, denken Sie daran, dass dies eine ist Schnittstelle Muster. Verwenden Sie es nicht für jede interne Klasse, die es gibt. Um Blade Runner zu zitieren, ich habe Scheiße gesehen, die ihr nicht glauben würdet.

    – DevSolar

    11. März 2013 um 14:24 Uhr

  • Seien Sie vorsichtig, PIMPL kann viele Vorteile haben, insbesondere in größeren Projekten, kann aber ein ansonsten einfaches, kleineres Programm ernsthaft komplizieren. Irgendwann in dieser Frage gab es eine Liste mit minimalen “Voraussetzungen” für die Verwendung von PIMPL in einem Projekt. Nicht jeder sollte der gleichen Liste folgen, eine für sich selbst erstellen und sich daran halten. Das ist meiner Meinung nach wahrscheinlich der beste Weg, es zu tun.

    – Osirisgothra

    8. Februar 2014 um 8:20 Uhr

  • Meine eigene Erfahrung ist, dass Pimpl von Leuten bevorzugt wird, die große undokumentierte Frameworks produzieren und dann das Unternehmen verlassen, so dass ihre ehemaligen Kollegen damit umgehen müssen, dass die Klassifizierung besonders schwer zu analysieren ist … .

    – Trantor

    24. Januar 2017 um 15:44 Uhr

Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Rob Wells

Ich denke, die meisten Leute bezeichnen dies als die Griffkörper Idiom. Siehe das Buch von James Coplien Fortgeschrittene C++-Programmierstile und Redewendungen. Es ist auch als bekannt Grinsekatze durch Lewis Carolls Charakter, der verblasst, bis nur noch das Grinsen übrig bleibt.

Der Beispielcode sollte auf zwei Gruppen von Quelldateien verteilt werden. Nur dann Kat.h ist die Datei, die mit dem Produkt geliefert wird.

CatImpl.h ist enthalten von Kat.cpp und CatImpl.cpp enthält die Implementierung für CatImpl::Purr(). Dies ist für die Öffentlichkeit, die Ihr Produkt verwendet, nicht sichtbar.

Grundsätzlich geht es darum, so viel wie möglich von der Implementierung vor neugierigen Blicken zu verbergen.

Dies ist am nützlichsten, wenn Sie ein kommerzielles Produkt haben, das als eine Reihe von Bibliotheken geliefert wird, auf die über eine API zugegriffen wird, mit der der Code des Kunden kompiliert und verknüpft wird.

Wir haben dies mit der Neufassung von getan IONAs Orbix 3.3 Produkt im Jahr 2000.

Wie von anderen erwähnt, entkoppelt die Verwendung seiner Technik die Implementierung vollständig von der Schnittstelle des Objekts. Dann müssen Sie nicht alles neu kompilieren, was verwendet wird Katze wenn Sie nur die Implementierung von ändern möchten Schnurren().

Diese Technik wird in einer Methodik namens verwendet Vertragsgestaltung.

  • @Rob, ich vermute, es gibt sehr wenig Aufwand dafür. Eine Extraklasse, aber es gibt sehr wenig zu ihnen. Nur eine dünne Hülle um die bestehende Klasse. Jemand korrigiert mich, wenn ich falsch liege, aber die Speichernutzung wäre nur eine zusätzliche Funktionstabelle im RAM, ein Zeiger auf den Pimpl und eine Umleitungsfunktion für jede Methode im Codespace. Schmerzhaft für Wartung und Debugging.

    – JeffV

    16. September 2008 um 23:26 Uhr


  • Wie wird die Noppen-Ideologie (oder Handle-Body-Ideologie, wie Sie es nennen) im Vertragsdesign verwendet?

    – andreas buykx

    22. September 2008 um 20:35 Uhr

  • Hallo Andreas, Ihr Schnittstellenpunkt zu einem API-Benutzer liegt nur im exponierten Vertrag (Handle) und nicht in der Art und Weise, wie Sie den Körper implementieren, um die beworbene Funktionalität bereitzustellen. Es steht Ihnen frei, die Implementierung nach eigenem Ermessen zu ändern, vorausgesetzt, Sie ändern nicht die Semantik der von Ihnen beworbenen API.

    – Rob Wells

    5. Dezember 2014 um 16:50 Uhr


  • @RobWells Ich habe diese Antwort abgelehnt, weil sie auch falsch ist (aber nicht so falsch wie die akzeptierte; diese könnte möglicherweise behoben werden). Probleme: a) “Grundsätzlich geht es darum, so viel wie möglich von der Implementierung vor neugierigen Blicken zu verbergen.” Wie unterscheidet es sich von einer einfachen .h/.cpp Klassendeklaration/Definitionstrennung und Versandbibliothek als .h/(.a|.lib)? Es verbirgt auch offensichtlich die Implementierung vor dem Client. Das hat der OP erwähnt ausdrücklich in der Frage!

    – cubuspl42

    11. April 2019 um 8:18 Uhr


  • FFR: Beziehen Sie sich grundsätzlich auf die akzeptierte Antwort in stackoverflow.com/questions/8972588/…

    – cubuspl42

    11. April 2019 um 8:24 Uhr

1647082212 774 Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Xaver Nodet

  • Weil du willst Purr() in der Lage zu sein, private Mitglieder von zu verwenden CatImpl. Cat::Purr() wäre ein solcher Zugriff nicht gestattet ohne a friend Erklärung.
  • Denn dann mischt man die Verantwortlichkeiten nicht: Eine Klasse setzt um, eine Klasse leitet weiter.

  • Es ist jedoch ein Schmerz, es aufrechtzuerhalten. Aber andererseits, wenn es sich um eine Bibliotheksklasse handelt, sollten die Methoden sowieso nicht viel geändert werden. Der Code, den ich mir anschaue, scheint den sicheren Weg zu gehen und überall Pimpl zu verwenden.

    – JeffV

    13. September 2008 um 15:23 Uhr

  • Ist diese Zeile nicht illegal, da alle Mitglieder privat sind: cat_->Purr(); Purr() ist von außen nicht zugänglich, da es standardmäßig privat ist. Was fehlt mir hier?

    – binärer Kerl

    14. August 2015 um 9:20 Uhr


  • Beide Punkte machen keinen Sinn. Wenn du eine Klasse hättest – Cat Es wäre auch in der Lage, auf seine Mitglieder zuzugreifen, und es würde keine “Reposbilities mischen”, da es die Klasse wäre, die “implementiert”. Die Gründe für den Einsatz von PIMPL sind unterschiedlich.

    – mip

    10. Januar 2017 um 13:32 Uhr


  • Diese Antwort ist aus den von @doc genannten Gründen einfach falsch. Es wäre absurd, eine neue Klasse einzuführen, nur um ihre privaten Mitglieder zu verwenden, und es ist keine “Verantwortung”, etwas einfach weiterzuleiten!

    – cubuspl42

    11. April 2019 um 8:00 Uhr

1647082213 218 Warum sollte die Redewendung „PIMPL verwendet werden duplicate
das Schwein

Für das, was es wert ist, trennt es die Implementierung von der Schnittstelle. Dies ist normalerweise bei kleinen Projekten nicht sehr wichtig. In großen Projekten und Bibliotheken kann es jedoch verwendet werden, um die Build-Zeiten erheblich zu verkürzen.

Bedenken Sie, dass die Umsetzung von Cat kann viele Header enthalten, kann Template-Metaprogrammierung beinhalten, deren Kompilierung Zeit in Anspruch nimmt. Warum sollte ein Benutzer, der nur die verwenden möchte Cat muss das alles beinhalten? Daher werden alle notwendigen Dateien mit dem Pimpl-Idiom versteckt (daher die Vorwärtsdeklaration von CatImpl), und die Verwendung der Schnittstelle zwingt den Benutzer nicht, sie einzuschließen.

Ich entwickle eine Bibliothek für die nichtlineare Optimierung (lesen Sie “viel böse Mathematik”), die in Vorlagen implementiert ist, sodass sich der größte Teil des Codes in Headern befindet. Es dauert ungefähr fünf Minuten, um zu kompilieren (auf einer anständigen Multi-Core-CPU) und nur die Header in einem ansonsten leeren Bereich zu analysieren .cpp dauert etwa eine Minute. Jeder, der die Bibliothek verwendet, muss also jedes Mal ein paar Minuten warten, wenn er seinen Code kompiliert, was die Entwicklung ziemlich macht langweilig. Indem man jedoch die Implementierung und die Header verbirgt, bindet man nur eine einfache Schnittstellendatei ein, die sofort kompiliert wird.

Es hat nicht unbedingt etwas damit zu tun, die Implementierung vor dem Kopieren durch andere Unternehmen zu schützen – was wahrscheinlich sowieso nicht passieren würde, es sei denn, das Innenleben Ihres Algorithmus kann aus den Definitionen der Elementvariablen erraten werden (falls ja wahrscheinlich nicht sehr kompliziert und überhaupt nicht schützenswert).

1647082213 71 Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Nick

Wenn Ihre Klasse das PIMPL-Idiom verwendet, können Sie vermeiden, die Header-Datei in der öffentlichen Klasse zu ändern.

Dadurch können Sie der PIMPL-Klasse Methoden hinzufügen/entfernen, ohne die Header-Datei der externen Klasse zu ändern. Sie können auch #includes zur PIMPL hinzufügen/entfernen.

Wenn Sie die Header-Datei der externen Klasse ändern, müssen Sie alles neu kompilieren, was sie enthält (und wenn es sich um Header-Dateien handelt, müssen Sie alles neu kompilieren, was sie enthält, und so weiter).

1647082213 655 Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Wilka

Normalerweise ist der einzige Verweis auf eine PIMPL-Klasse im Header für die Eigentümer Klasse (Katze in diesem Fall) wäre eine Forward-Deklaration, wie Sie es hier getan haben, da dies die Abhängigkeiten stark reduzieren kann.

Zum Beispiel, wenn Ihre PIMPL-Klasse hat Komplizierte Klasse als Mitglied (und nicht nur einen Zeiger oder Verweis darauf) müssten Sie dann haben Komplizierte Klasse vor seiner Verwendung vollständig definiert. In der Praxis bedeutet dies, die Datei “ComplicatedClass.h” einzuschließen (die indirekt auch alles enthalten wird Komplizierte Klasse kommt drauf an). Dies kann dazu führen, dass eine einzelne Header-Füllung viele, viele Dinge mit sich bringt, was schlecht für die Verwaltung Ihrer Abhängigkeiten (und Ihrer Kompilierungszeiten) ist.

Wenn Sie das PIMPL-Idiom verwenden, müssen Sie nur die Dinge #einschließen, die in der öffentlichen Schnittstelle Ihrer verwendet werden Eigentümer Typ (was wäre Katze Hier). Das macht die Dinge für Leute, die Ihre Bibliothek benutzen, besser und bedeutet, dass Sie sich keine Sorgen machen müssen, dass Leute von einem internen Teil Ihrer Bibliothek abhängig sind – entweder aus Versehen oder weil sie etwas tun wollen, das Sie nicht zulassen, also # Definieren Sie private public, bevor Sie Ihre Dateien einschließen.

Wenn es sich um eine einfache Klasse handelt, gibt es normalerweise keinen Grund, ein PIMPL zu verwenden, aber in Zeiten, in denen die Typen ziemlich groß sind, kann es eine große Hilfe sein (insbesondere um lange Build-Zeiten zu vermeiden).

Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Peter Mortensen

Nun, ich würde es nicht verwenden. Ich habe eine bessere Alternative:

Datei foo.h

class Foo {
public:
    virtual ~Foo() { }
    virtual void someMethod() = 0;

    // This "replaces" the constructor
    static Foo *create();
}

Datei foo.cpp

namespace {
    class FooImpl: virtual public Foo {

    public:
        void someMethod() {
            //....
        }
    };
}

Foo *Foo::create() {
    return new FooImpl;
}

Hat dieses Muster einen Namen?

Als jemand, der auch Python- und Java-Programmierer ist, gefällt mir das viel mehr als das PIMPL-Idiom.

Warum sollte die Redewendung „PIMPL verwendet werden duplicate
Peter Mortensen

Wenn Sie den Aufruf von impl->Purr in die .cpp-Datei einfügen, können Sie in Zukunft etwas völlig anderes tun, ohne die Header-Datei ändern zu müssen.

Vielleicht entdecken sie nächstes Jahr eine Hilfsmethode, die sie stattdessen hätten aufrufen können, und so können sie den Code ändern, um diese direkt aufzurufen und überhaupt nicht impl->Purr zu verwenden. (Ja, sie könnten dasselbe erreichen, indem sie auch die eigentliche impl::Purr-Methode aktualisieren, aber in diesem Fall bleiben Sie mit einem zusätzlichen Funktionsaufruf hängen, der nichts anderes bewirkt, als die nächste Funktion der Reihe nach aufzurufen.)

Es bedeutet auch, dass der Header nur Definitionen und keine Implementierung hat, was für eine sauberere Trennung sorgt, was der springende Punkt der Redewendung ist.

993420cookie-checkWarum sollte die Redewendung „PIMPL“ verwendet werden? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy