Frage

Wie ich verstehe, existiert die PimPL -Idiom nur, weil C ++ Sie dazu zwingt, alle privaten Klassenmitglieder in den Kopfball zu platzieren. Wenn der Header nur die öffentliche Schnittstelle enthalten würde, hätte eine Änderung der Klassenimplementierung für den Rest des Programms keinen Neukompilieren erforderlich.

Ich möchte wissen, warum C ++ nicht so konzipiert ist, dass eine solche Bequemlichkeit zulässig ist. Warum verlangt es überhaupt, dass die privaten Teile einer Klasse offen im Header angezeigt werden (kein Wortspiel beabsichtigt)?

War es hilfreich?

Lösung

Dies hat mit der Größe des Objekts zu tun. Die H -Datei wird unter anderem verwendet, um die Größe des Objekts zu bestimmen. Wenn die privaten Mitglieder nicht darin gegeben werden, würden Sie nicht wissen, wie groß ein Objekt für neu ist.

Sie können jedoch Ihr gewünschtes Verhalten durch Folgendes simulieren:

class MyClass
{
public:
   // public stuff

private:
#include "MyClassPrivate.h"
};

Dies erzwingt das Verhalten nicht, aber es bringt das private Zeug aus der .h -Datei heraus. Auf der Abwärtsseite fügt dies eine andere Datei hinzu, um die Wartung zu verwalten. In Visual Studio funktioniert das IntelliSense auch für die privaten Mitglieder nicht - dies könnte ein Plus oder ein Minus sein.

Andere Tipps

Ich denke, hier gibt es eine Verwirrung. Das Problem geht nicht über Header. Header tun nichts (sie sind nur Möglichkeiten, gemeinsame Quelltext-Teile in mehreren Quellcode-Dateien aufzunehmen).

Das Problem, so sehr es eines gibt, ist, dass Klassenerklärungen in C ++ alles definieren müssen, öffentlich und privat, dass eine Instanz haben muss, um zu arbeiten. (Gleiches gilt für Java, aber die Art und Weise, wie sich die Arbeiten auf extern kompilierte Arbeiten beziehen, macht die Verwendung von gemeinsam genutzten Headern unnötig.)

In der Art der gängigen objektorientierten Technologien (nicht nur der C ++) muss jemand die konkrete Klasse kennen und wie er seinen Konstruktor verwendet, um eine Implementierung zu liefern, selbst wenn Sie nur die öffentlichen Teile verwenden. Das Gerät in (3, unten) verbirgt es. Die Praxis in (1, unten) trennt die Bedenken, unabhängig davon, ob Sie (3) oder nicht.

  1. Verwenden Sie abstrakte Klassen, die nur die öffentlichen Teile, hauptsächlich Methoden, definieren, und lassen Sie die Implementierungsklasse aus dieser abstrakten Klasse erben. Mit der üblichen Konvention für Header gibt es also eine Zusammenfassung. Es gibt auch eine Implementierung. Die Datei der Implementierung.hPP wird "Abstract.hpp" für die Verwendung in der Klassenerklärung #Include "so ein einziger Wartungspunkt für die Deklaration der abstrahierten Schnittstelle vorhanden.

  2. Wenn Sie nun das Verstecken der Erklärung zur Implementierungsklasse durchsetzen möchten, müssen Sie eine Möglichkeit haben, die Konstruktion einer konkreten Instanz zu beantragen, ohne die spezifische, vollständige Klassenerklärung zu besitzen: Sie können keine Neue verwenden und Sie können keine lokalen Instanzen verwenden . (Sie können jedoch löschen.) Einführung von Helferfunktionen (einschließlich Methoden zu anderen Klassen, die Verweise auf Klasseninstanzen liefern) ist der Ersatz.

  3. Zusammen mit oder als Teil der Header -Datei, die als gemeinsam genutzte Definition für die abstrakte Klasse/Schnittstelle verwendet wird, enthalten Funktionssignaturen für externe Helferfunktionen. Diese Funktion sollte in Modulen implementiert werden, die Teil der spezifischen Klassenimplementierungen sind (so sehen sie die vollständige Klassenerklärung und können den Konstruktor ausüben). Die Signatur der Helferfunktion ähnelt wahrscheinlich der des Konstruktors, gibt jedoch als Ergebnis eine Instanzreferenz zurück (dieser Konstruktorproxy kann einen Nullzeiger zurückgeben und sogar Ausnahmen werfen, wenn Sie so etwas mögen). Die Helferfunktion konstruiert eine bestimmte Implementierungsinstanz und gibt sie als Verweis auf eine Instanz der abstrakten Klasse zurück.

Mission erfüllt.

Oh, und die Neukompilierung und das Relinking sollten so funktionieren, wie Sie möchten, und vermeiden Sie die Neukompilierung von Aufrufmodulen, wenn sich nur die Implementierung ändert (da das aufgerufene Modul keine Speicherzuweisungen für die Implementierungen mehr erstellt).

Sie alle ignorieren den Punkt der Frage -

Warum muss der Entwickler den PIMPL -Code eingeben?

Für mich ist die beste Antwort, die ich mir einfallen lassen kann, dass wir keine gute Möglichkeit haben, C ++ - Code auszudrücken, mit dem Sie darauf arbeiten können. Zum Beispiel Kompilierungszeit (oder Pre-Processor oder was auch immer) oder ein Code-DOM.

C ++ braucht dringend einen oder beide, um einem Entwickler eine Metaprogrammierung durchzuführen.

Dann könnten Sie so etwas in Ihrer öffentlichen Myclass schreiben.

#pragma pimpl(MyClass_private.hpp)

Und dann schreiben Sie Ihren eigenen, wirklich ziemlich trivialen Wrapper -Generator.

Jemand wird eine viel ausführlichere Antwort haben als ich, aber die schnelle Antwort ist zweifach: Der Compiler muss alle Mitglieder einer Struktur kennen, um die Anforderungen des Speicherplatzes zu bestimmen, und der Compiler muss die Bestellung dieser Mitglieder kennen Erzeugen Sie Offsets auf deterministische Weise.

Die Sprache ist bereits ziemlich kompliziert; Ich denke, ein Mechanismus, um die Definitionen strukturierter Daten im Code zu teilen, wäre ein bisschen Unglück.

Normalerweise habe ich immer gesehen Richtlinienklassen Wird verwendet, um das Implementierungsverhalten in einem Pimpl-Manner zu definieren. Ich denke, es gibt einige zusätzliche Vorteile der Verwendung eines Richtlinienmusters - einfacher zu interchange die Implementierung und kann problemlos mehrere Teilimplementierungen zu einer einzigen Einheit kombinieren, mit denen Sie den Implementierungscode in funktionale, wiederverwendbare Einheiten usw. zerlegen können.

Kann daran liegen, dass die Größe der Klasse erforderlich ist, wenn sie ihre Instanz durch Werte verabschiedet, in anderen Klassen usw. aggregiert wird?

Wenn C ++ keine Wertsemantik unterstützt hätte, wäre es in Ordnung gewesen, aber das tut es.

Ja aber...

Sie müssen Strousstrups "Design and Evolution of C ++" -Buch lesen. Es hätte die Aufnahme von C ++ gehemmt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top