Abgeleitet von StreamBuf ohne Umschreiben eines entsprechenden Streams
Frage
Vor einigen Tagen habe ich beschlossen, dass es Spaß machen würde, a zu schreiben streambuf
Unterklasse, die verwenden würden mmap
und Read-Ahead. Ich habe mir angesehen, wie mein STL (SGI) implementiert wurde filebuf
und erkannte das basic_filebuf
enthält ein FILE*
. Also Erben von basic_filebuf
ist nicht in Frage.
Also habe ich von geerbt basic_streambuf
. Dann wollte ich meine binden mmapbuf
zu einem Fstream.
Ich dachte, das einzige, was ich tun müsste, wäre, die implizite Schnittstelle von zu kopieren filebuf
... aber das war ein klarer Fehler. Im SGI, basic_fstream
besitzt a basic_filebuf
. Egal, ob ich anrufe basic_filestream.std::::ios::rdbuf( streambuf* )
, der fileStream ignoriert es vollständig und verwendet seine eigene filebuf
.
Jetzt bin ich ein bisschen verwirrt ... sicher, ich kann meine eigenen erstellen mmfstream
, das wäre die genaue Kopie/Einfüge der fstream
Aber das klingt wirklich nicht trocken orientiert.
Was ich nicht verstehen kann, ist: warum tut fstream
ist so eng mit filebuf
, damit es nicht möglich ist, etwas anderes als a zu verwenden filebuf
? Der springende Punkt der Trennung von Streams und Bufs ist, dass man einen Stream mit einem anderen Puffer verwenden kann.
Lösungen:
=> filestream
sollte sich auf die implizite Schnittstelle von verlassen filebuf
. Das heißt, Fstream sollte von einer Streambuf -Klasse vorgeschubt werden. Das würde es jedem ermöglichen, eine eigene Streambuf -Unterklasse für a zu geben fstream
Solange es impliziert filebuf
Implizite Schnittstelle. Problem: Wir können keinen Vorlagenparameter hinzufügen fstream
Da würde es die Vorlagenauswahlsportler unter Verwendung des Gebrauchs unterbrechen fstream
als Vorlagenvorlageparameter.
=> filebuf
sollte eine reine virtuelle Klasse ohne zusätzliche Attribute sein. Damit man sich daraus erben kann, ohne all seine Datei* Müll zu tragen.
Ihre Ideen zu diesem Thema?
Lösung
Kasse Zugeordneter in dem Boost.IOStreams Bibliothek. Ich habe es selbst nie benutzt, aber es scheint, als hätte es bereits das tun, was Sie brauchen.
Bearbeiten: Oops, lesen Sie Ihre Fragen noch einmal und ich sehe, dass Sie dies zum Spaß tun. Vielleicht können Sie sich von Boost.isistreams inspirieren lassen?
Andere Tipps
Im Entwurf der IO -Streams werden die meisten Funktionen der tatsächlichen Streams (im Gegensatz zur Funktionalität der Streampuffer) implementiert in std::basic_istream
, std::basic_ostream
, und ihre Basisklassen. Die String- und Dateistreamklassen sind mehr oder weniger nur bequeme Wrapper, die sicherstellen, dass ein Stream mit dem richtigen Puffertyp instanziiert ist.
Wenn Sie die Streams erweitern möchten, Sie möchten fast immer Ihre zur Verfügung stellen eigene Stream -Pufferklasse, und Sie müssen fast nie Ihren eigenen Stream -Kurs anbieten. .
Sobald Sie Ihren eigenen Stream -Puffer -Typ haben, können Sie ihn zum Puffer für jedes Stream -Objekt machen, das Sie zufällig haben. Oder Sie leiten Ihre eigenen Klassen ab von std::basic_istream
, std::basic_ostream
, und std::basic_iostream
Was Ihren Stream -Puffer instanziiert und an ihre Basisklassen weiterleitet.
Letzteres ist für Benutzer bequemer, erfordert jedoch, dass Sie einen Kesselplattencode für die Instanziierung des Puffer (nämlich Konstruktoren für die Stream-Klasse) schreiben.
Um Ihre Frage zu beantworten: Dateiströme und Dateipuffer sind so fest gekoppelt, weil erstere nur existiert, um die Erstellung des letzteren zu erleichtern. Wenn Sie einen Dateistrom verwenden, können Sie alles einfach einstellen.
Wenn Sie Ihre eigene Stream -Klasse verwenden, um die Konstruktion Ihres eigenen Stream -Puffers zu wickeln, sollte kein Problem sein, da Sie sowieso keine Dateiströme, sondern nur (Referenzen) an die Basisklassen weitergeben sollten.
fstream
An sich ist keine große Klasse. Es erbt von basic_stream
Um alle Unterstützung zu unterstützen <<
und >>
Operationen enthält eine spezialisierte steambuf
die initialisiert werden müssen, und die entsprechenden Konstruktoren, um die Parameter an die zu übergeben streambuf
Konstrukteur.
In gewisser Weise ist das, was Sie über Ihre Vorlagenlösung geschrieben haben, in Ordnung. Aber basic_stream
kann auch in a abgeleitet werden tcp_stream
zum Beispiel. In diesem Fall die Konstrukteure von fstream
sind ein bisschen nutzlos. Daher müssen Sie eine neue bereitstellen tcpstream
Klasse, Erben von basic_stream
mit den richtigen Parametern, damit die Konstrukteure das erstellen können tcp_stream
. Am Ende würden Sie nichts von verwenden fstream
. Dieses neue erstellen tcpstream
ist nur 3 oder 4 Funktionen zu schreiben.
Am Ende würden Sie von der abgeleitet fstream
Klasse ohne wirklichen Grund. Dies würde eine mehr Kopplung in der Klassenhierarchie und der nicht benötigten Kopplung hinzufügen.
Der springende Punkt von std::fstream
ist, dass es ein _ istF_ilbasiert std::stream
. Wenn Sie ein gewöhnliches wollen std::stream
von Ihrem unterstützt mmstreambuf
, dann sollten Sie eine erstellen mmstreambuf
und weitergeben std::stream::stream(std::streambuf*)