Operatoren müssen keine Member-Funktionen sein, sondern werden als globale Funktionen eingeführt, wobei ein Ausgabe-Operator als Argument eine Referenz auf einen ostream (bzw. basic_ostream) und eine Referenz auf die auszugebende Variable enthält und eine Referenz auf sich selbst zurückgibt. Eingabe-Operatoren werden analog dazu erstellt.
Beispiel: std::ostream& operator << (std::ostream&, CString&); std::istream& operator >> (std::istream&, std::stream&);
Für die Standard-Datentypen sind ostream bzw. istream bereits überladen. Wenn man eigene Operatoren definiert, versucht man zuerst, den ein-/auszugebenden Datentyp auf die Standard-Datentypen zurückzuführen.
Beispiel: std::ostream& operator << (std::ostream& ostr, CString& cstr) {  : return(ostr << (LPTCSTR) cstr); }
Im Zweifelsfall kann man den Datentyp immer auf den Typ char zurückführen. Man kann sich auch der Funktionen istream::get(), istream::getline() und ostream::put() bedienen.
Bei der Deklaration von Operatoren für eigene Klassen muss man die Zugriffskontrolle beachten. Für die Ein-/Ausgabe von nicht-public Daten muss der Operator in der Klassen-Deklaration als friend eingeführt werden.
Mit den Operatoren std::ostream& operator << (std::ostream&, CString&); std::ostream& operator << (std::ostream&, std::string&);
std::ostream& operator << (std::ostream& ostr, CString& cstr) {  : return(ostr << (LPTCSTR) cstr); }
std::ostream& operator << (std::ostream& ostr, std::string& sstr) {  : return(ostr << sstr.c_str()); }
ergibt sich das obige Beispiel zu:
OG_constream text_fenster;
int i = 10; double d = 3.14156; std::string sstr("STL String"); CString cstr("Microsoft CString");
text_fenster << "i = " << i << std::endl; text_fenster << "d = " << d << std::endl; text_fenster << "STL String = " << sstr << std::endl; text_fenster << "Microsoft CString = " << cstr << std::endl;