Frage

Es ist allgemein bekannt, dass der Benutzer Strom Manipulatoren wie folgt definieren:

ostream& tab(ostream & output)
{
    return output<< '\t';
} 

Und dies kann verwendet werden in main () wie folgt aus:

cout<<'a'<<tab<<'b'<<'c'<<endl;

Bitte erklären Sie mir, wie funktioniert das alles? Wenn Operator << übernimmt als zweiten Parameter einen Zeiger auf die Funktion, die und kehrt nimmt ostream & , dann meine bitte erklären, warum es notwendig ist? Was wäre falsch, wenn die Funktion nicht übernimmt und zurück ostream & , aber es war void statt ostream & ?

Auch ist es interessant, warum „Dezember“, „hex“ Manipulatoren wirksam, bis ich zwischen ihnen nicht ändern, aber benutzerdefinierten Manipulatoren sollten immer um wirksam zu werden für jedes Streaming verwendet werden?

War es hilfreich?

Lösung

Der Standard definiert die folgende operator<< Überlastung in der basic_ostream Klassenvorlage:

basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& (*pf) (basic_ostream<charT,traits>&) );

Effekte: Keine. Verhält sich nicht als formatierte Ausgabefunktion (wie in 27.6.2.5.1 beschrieben).

Returns:. pf(*this)

Der Parameter ist ein Zeiger auf eine Funktion Mitnahmen und einen Verweis auf einen std::ostream zurück.

Das bedeutet, dass man „Strom“ eine Funktion mit dieser Signatur zu einem ostream Objekt und es hat den Effekt, dass die Funktion auf dem Stream aufrufen. Wenn Sie den Namen einer Funktion in einem Ausdruck verwenden dann ist es (in der Regel) umgewandelt in einen Zeiger auf diese Funktion.

std::hex ist ein std::ios_base Manipulators wie folgt definiert.

   ios_base& hex(ios_base& str);

Effekte:. Anrufe str.setf(ios_base::hex, ios_base::basefield)

Returns: Str.

Das bedeutet, dass hex Streaming zu einem ostream die Ausgangsbasis eingestellt werden Flags Ausgabezahlen in hexadezimale Formatierung. Der Manipulator nichts ausgibt selbst.

Andere Tipps

Es ist nichts falsch mit ihm, außer es keine Überlastung Operator << für sie definiert. Die bestehenden Überlastungen für << werden einen Manipulator mit der Unterschrift ostream & (* fp) (ostream &) zu erwarten.

Wenn Sie es einen Manipulator mit dem Typ gab ostream & (* fp) () Sie würde einen Compiler-Fehler, da es nicht haben eine Definition für Operator << (ostream &, ostream & (* fp) ()) . Wenn Sie diese Funktionalität wollen würden Sie den Operator << zu akzeptieren Manipulatoren dieses Typs überlasten müssen.

würden Sie haben eine Definition für diese schreiben:
ostream & ostream :: operator << (ostream & (* m) ())

Beachten Sie hier, dass nichts Magisches hier geschieht. Die Strombibliotheken verlassen sich stark auf Standard C ++ Funktionen: Überladen von Operatoren, Klassen und Referenzen.

Nun, da Sie wissen, wie Sie die Funktionen erstellen können, die Sie beschrieben, ist hier, warum wir es nicht tun:

Ohne einen Verweis auf den Strom geben wir zu manipulieren versuchen, können wir nicht auf den Strom, Änderungen verbunden Endvorrichtung (cin, out, err, fstream, etc). Die Funktion (Modifizierers sind alle nur Funktionen mit Phantasienamen) würde entweder ein neues Ostream zurückzukehren, die nichts mit dem man nach links von dem Operator << zu tun hatten, oder durch einigen sehr hässlichen Mechanismus, herauszufinden, welche oStream es sollte Verbindung mit anderen allem nach rechts des Modifizierungs wont es das Endgerät, sondern vielmehr, was auch immer oStream die Funktion / Modifikator zurück gesendet wird.

Denken Sie an Ströme wie diese

cout << "something here" << tab << "something else"<< endl;

wirklich bedeutet

(((cout << "something here") << tab ) << "something else" ) << endl);

wobei jeder Satz von Klammern tut etwas cout (schreiben, ändern usw.) und dann kehrt cout so der nächste Satz von Klammern kann daran arbeiten.

Wenn Sie Ihre Registerkarte Modifikator / Funktion nicht einen Verweis auf ein ostream nehmen haben müßte es irgendwie erraten, was Ostream nach links von dem Operator << war seine Aufgabe zu erfüllen. Waren Sie mit cour arbeiten, cerr, ... einige Datei-Stream? Die Interna der Funktion wird nie wissen, es sei denn, sie, die Informationen etwas wie geben werden, und warum nicht, dass, wie sein so einfach wie ein Hinweis auf sie.

Nun, um wirklich den Punkt nach Hause fahren, schauen wir uns an, was Endl wirklich ist und die überladene Version des << Operator wir verwenden:

Dieser Operator sieht wie folgt aus:

  ostream& ostream::operator<<(ostream& (*m)(ostream&)) 
  {  
      return (*m)(*this);
  }

Endl sieht wie folgt aus:

  ostream& endl(ostream& os)      
  {  
      os << '\n'; 
      os.flush();     
      return os;
  }

Der Zweck Endl ist eine neue Zeile hinzufügen und den Strom spülen, um sicherzustellen, alle Inhalte des internen Puffers Strom haben auf das Gerät geschrieben worden. Um dies zu tun, muss er zuerst ein ‚\ n‘ zu diesem Strom schreiben. Es muss dann den Strom zu bündig erzählen. Der einzige Weg für Endl zu wissen, welchem ??Strom zu schreiben und bündig ist für die Betreiber dieser Informationen an die endl Funktion zu übergeben, wenn er es nennt. Es wäre wie ich Ihnen sagen, mein Auto zu waschen, aber man kann nie sagen, welches Auto Mine im vollen Parkplatz ist. Sie würden nie Ihren Job erledigen können. Sie müssen mich zu jeder Hand Sie mein Auto oder ich kann es selbst waschen.

Ich hoffe, dass klärt die Dinge

PS -. Wenn Sie aus Versehen passieren zu meinem Auto finden, bitte waschen

Normalerweise setzt der Strom Manipulator einige Flags (oder andere Einstellungen) auf dem Stream-Objekt, so dass beim nächsten Mal verwendet wird, wird sie handelt nach den Flaggen. Der Manipulator daher gibt das gleiche Objekt seiner übergeben. Die operator<< Überlastung, die den Manipulator genannt hat bereits diese Aufgabe, natürlich, so wie Sie vielleicht bemerken, wird der Rückgabewert nicht genau für diesen Fall benötigt. Ich denke, das deckt alle Standard-Manipulatoren -. Sie alle Rückkehr ihre Eingabe

Doch mit dem Rückgabewert ist der Rahmen flexibel genug, dass ein benutzerdefinierte Stream Manipulator könnte ein anderes Objekt zurück, vermutlich einen Wrapper für das Objekt seiner gegeben. Das andere Objekt würde dann von cout << 'a' << tab zurückgegeben werden, und etwas tun könnte, dass die eingebauten ostream Formatierungseinstellungen nicht unterstützen.

Nicht sicher, wie Sie arrangieren würden für dieses andere Objekt freigegeben werden, obwohl, so dass ich weiß nicht, wie praktisch das ist. Es könnte etwas Besonderes sein, wie ein Proxy-Objekt, das von dem ostream selbst verwaltet wird. Dann würde der Manipulator nur Arbeit für benutzerdefinierte Stream-Klassen, dass sie aktiv unterstützen, die in der Regel nicht der Punkt der Manipulatoren ist.

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