Stream-Operatoren
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 43 von 104.
Die Stream-Einfüge- (<<) und Extraktions- (>>) Operatoren ermöglichen es Ihnen, Ihre benutzerdefinierten Klassen mit std::cout und std::cin zu verwenden. Im Gegensatz zu den Operatoren, die wir bisher behandelt haben, müssen diese als Nicht-Elementfunktionen implementiert werden, da der linke Operand ein Stream ist und nicht Ihre Klasse.
class Point {
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
// Als Friend deklarieren, um auf private Member zuzugreifen
friend std::ostream& operator<<(std::ostream& os, const Point& p);
friend std::istream& operator>>(std::istream& is, Point& p);
};
std::ostream& operator<<(std::ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
std::istream& operator>>(std::istream& is, Point& p) {
is >> p.x >> p.y;
return is;
}Beide Operatoren geben eine Referenz auf den Stream zurück, was eine Verkettung wie std::cout << p1 << p2 ermöglicht. Der Einfügeoperator nimmt das Objekt als const-Referenz entgegen, da er nur Daten liest, während der Extraktionsoperator eine Nicht-const-Referenz entgegennimmt, da er das Objekt verändert.
Nun können Sie Point natürlich mit Streams verwenden:
Point p(3, 4);
std::cout << "Location: " << p << std::endl; // Ausgabe: Location: (3, 4)
Point p2(0, 0);
std::cin >> p2; // Zwei Ganzzahlen in p2 einlesenAufgabe
EinfachLassen Sie uns eine Temperature-Klasse erstellen, die nahtlos mit std::cout und std::cin durch Überladen von Stream-Operatoren verwendet werden kann. Dies ist ein praktisches Szenario, in dem Sie Temperaturen in einem lesbaren Format anzeigen und sie natürlich aus der Eingabe lesen möchten.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
Temperature.h: Definieren Sie eineTemperature-Klasse, die einen Wert in Celsius (alsdouble) und ein Einheiten-Label (alschar, entweder'C'für Celsius oder'F'für Fahrenheit) speichert. Ihre Klasse sollte Folgendes enthalten:- Private Member für den Temperaturwert und die Einheit
- Einen Standardkonstruktor, der auf 0.0 Celsius initialisiert
- Einen parametrisierten Konstruktor, der einen Wert und eine Einheit entgegennimmt
- Getter
getValue()undgetUnit()(beide const) - Friend-Deklarationen für die Stream-Einfügung (
<<) und Stream-Extraktion (>>) Operatoren
Implementieren Sie die Stream-Operatoren als Nicht-Member-Funktionen:
- Der Einfügeoperator sollte die Temperatur im Format
VALUE UNITausgeben (z. B.25.5 Coder77.9 F). Verwenden Sie eine Dezimalstelle für den Wert. - Der Extraktionsoperator sollte einen Wert und ein Einheitenzeichen aus dem Stream lesen und diese im Temperature-Objekt speichern.
Beide Operatoren müssen eine Referenz auf den Stream zurückgeben, um Verkettung zu ermöglichen.
main.cpp: Lesen Sie zwei Temperaturen aus der Eingabe. Jede Temperatur wird in einer separaten Zeile im Formatvalue unitangegeben (z. B.25.5 C).Erstellen Sie zwei
Temperature-Objekte und verwenden Sie den Extraktionsoperator, um sie vonstd::cinzu lesen. Geben Sie sie dann mit dem Einfügeoperator in diesem Format aus:Temperature 1: <temp1> Temperature 2: <temp2>Wenn die Eingabe beispielsweise wie folgt aussieht:
25.5 C 98.6 FSollte die Ausgabe wie folgt lauten:
Temperature 1: 25.5 C Temperature 2: 98.6 F
Verwenden Sie std::fixed und std::setprecision(1) aus <iomanip>, um den Temperaturwert mit genau einer Dezimalstelle zu formatieren. Vergessen Sie nicht die Header-Guards in Ihrer Header-Datei.
Spickzettel
Stream-Einfüge- (<<) und Extraktions-Operatoren (>>) ermöglichen es benutzerdefinierten Klassen, mit std::cout und std::cin zu arbeiten. Diese Operatoren müssen als Nicht-Elementfunktionen implementiert werden, da der linke Operand ein Stream-Objekt ist und nicht Ihre Klasse.
Grundlegende Syntax
class Point {
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
// Als friend deklarieren, um auf private Member zuzugreifen
friend std::ostream& operator<<(std::ostream& os, const Point& p);
friend std::istream& operator>>(std::istream& is, Point& p);
};
std::ostream& operator<<(std::ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
std::istream& operator>>(std::istream& is, Point& p) {
is >> p.x >> p.y;
return is;
}Wichtige Punkte
- Beide Operatoren geben eine Referenz auf den Stream zurück, um eine Verkettung zu ermöglichen (z. B.
std::cout << p1 << p2) - Der Einfüge-Operator (
<<) nimmt das Objekt alsconst-Referenz entgegen, da er Daten nur liest - Der Extraktions-Operator (
>>) nimmt eine Nicht-const-Referenz entgegen, da er das Objekt modifiziert - Verwenden Sie
friend-Deklarationen, um diesen Nicht-Elementfunktionen den Zugriff auf private Member zu ermöglichen
Anwendungsbeispiel
Point p(3, 4);
std::cout << "Location: " << p << std::endl; // Ausgabe: Location: (3, 4)
Point p2(0, 0);
std::cin >> p2; // Zwei Ganzzahlen in p2 einlesenProbier es selbst
#include <iostream>
#include "Temperature.h"
int main() {
// TODO: Erstelle zwei Temperature-Objekte
// TODO: Verwende den Extraktionsoperator (>>), um zwei Temperaturen von std::cin einzulesen
// TODO: Gib die Temperaturen mit dem Einfügeoperator (<<) aus
// Format:
// Temperature 1: <temp1>
// Temperature 2: <temp2>
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamensräume & GültigkeitsbereicheEinführung in OOP in C++Klassen vs. ObjekteDer 'this'-PointerMethoden (Elementfunktionen)Attribute (Datenelemente)Grundlagen zu Ctors & DtorsRückblick - Einfacher Taschenrechner4Klasseneigenschaften
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen & KlassenZusammenfassung - Bankkonto-Manager7Vererbung
Grundlagen der VererbungZugriffsstufen bei VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick - Mitarbeiter-Hierarchie2Speicherverwaltung
Stack vs. Heap SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Smart Pointers in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsspezifizierer in C++Zugriffsspezifizierer im DetailInformation HidingStruct vs. ClassVerschachtelte & innere KlassenRückblick - Studentenverwaltungssystem8Polymorphie
Kompilierzeit- vs. Laufzeit-PolymorphieFunktionsüberladungVirtuelle Funktionen – WiederholungRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIZusammenfassung – Formen-Rechner3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorVerschiebekonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktoren im DetailRule of Three / Five / ZeroZusammenfassung - String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladen der [] und () OperatorenTypumwandlungsoperatorenRückblick - Matrix-Klasse9Templates
FunktionstemplatesKlassentemplatesTemplate-SpezialisierungVariadische TemplatesSFINAE & Type Traits GrundlagenRückblick - Generische Container