<< überladen



  • Warum geht das nicht? Ich möchte den operator << überladen, aber mit einer Funktion außerhalb der Klasse.

    #include <iostream>
    using namespace std;
    
    class math
    {
        public:
        math(int a);
        int Get_a() {return a;}
        private:
        int a;
    };
    
    void operator<<(ostream out,math object);
    
    math::math(int a)
    :a(a)
    {
    
    }
    
    int main()
    {
        math rechnen(5);
        cout << rechnen;
    
        return 0;
    }
    
    void operator<<(ostream out,math object)
    {
        cout << object.Get_a();
    }
    

    ERRORS:

    c:/mingw/bin/../lib/gcc/mingw32/3.4.4/../../../../include/c++/3.4.4/bits/ios_base.h:781: error: std::ios\_base::ios\_base(const std::ios\_base&)' is private C:\\MinGW\\Andi\\C++\\coutoperatorüberladen.cpp:26: error: within this context C:\\MinGW\\Andi\\C++\\coutoperatorüberladen.cpp: In functionint main()':
    C:\MinGW\Andi\C++\coutoperatorüberladen.cpp:26: error: initializing argument 1 of `void operator<<(std::ostream, math)'
    Process terminated with status 1 (0 minutes, 0 seconds)
    3 errors, 0 warnings

    Dankeschön schon mal im Voraus.



  • Du musst ein ostream-Objekt per reference übergeben, weil der Konstruktor private ist. Außerdem macht es keinen Sinn, cout als ostream zu benutzen, wenn dir ein Stream als Parameter übergeben wird. Drittens ist der Rückgabetyp des Operators der Stream, damit man den Operator mehrmals hintereinander aufrufen kann.

    Sieht dann also so aus:

    ostream& operator<<(ostream& out, const math& object)
    {
        out << object.Get_a();
        return out;
    }
    


  • Wenn Du 'operator <<' für 'std::ostream' definieren möchtest, verwende folgende Signatur:

    std::ostream& operator <<(std::ostream& out, math const& obj);
    

    Das stellt zwei Dinge sicher:

    - Es wird keine Kopie Deines Objekts und des Streams erzeugt (wie die Fehlermeldung sagt, geht das auch gar nicht) erzeugt.
    - Du kannst '<<' verketten, so wie Du es gewöhnt bist, z.B. in 'cout << a << endl;'.



  • Jetzt wollte ich ">>" überladen, aber was mach ich falsch? Hab jetzt das "cin >> A" noch nicht hinzugefügt weil sonst noch viel mehr Errors kommen.

    ERROR:
    C:\MinGW\Andi\C++\klammer überladen.cpp:28: error: no match for 'operator>>' in 'in >> temp'
    C:\MinGW\Andi\C++\klammer überladen.cpp:26: note: candidates are: void operator>>(std::ostream&, math&)

    #include <iostream>
    using namespace std;
    
    class math
    {
        public:
        math();
        void SetZahl(int a) {Zahl=a;}
        int GetZahl() {return Zahl;}
        private:
        int Zahl;
    };
    
    void operator>>(ostream &in,math &object);
    
    int main()
    {
        math A;
    
        return 0;
    }
    
    void operator>>(ostream &in,math &object)
    {
        int temp;
        in >> temp;
        object.SetZahl(temp);
    }
    


  • Hmm, wie kommst Du denn auf diese komische Signatur? Operator >> braucht als ersten Parameter natürlich einen 'istream' und keinen 'ostream' und muss, genauso wie auch op<< den Stream auch wieder zurückgeben. Entsprechend muss dann natürlich auch die Implementierung aussehen. Du hast vor allem vergessen, auf eine gültige Eingabe zu prüfen:

    istream& operator >>(istream& in, math& object)
    {
        int temp;
        if (not in >> temp) return in; // Fehler beim Einlesen.
        object.SetZahl(temp);
        return in;                     // Stream zurückgeben.
    }
    


  • Mh ich verstehe das noch nicht so ganz 🙂
    Also sowie ich das bis jetzt verstanden habe würde ich es so machen:

    #include <iostream>
    using namespace std;
    
    class math
    {
        public:
        math();
        void SetZahl(int a) {Zahl=a;}
        int GetZahl() {return Zahl;}
        private:
        int Zahl;
    };
    math::math()
    {
    
    }
    istream& operator >>(istream& in, math& object);
    int main()
    {
        math A;
        cin>>A;
    
        return 0;
    }
    istream& operator >>(istream& in, math& object)
    {
        int temp;
        in >> temp;
        object.SetZahl(temp);
        return in;
    }
    

    Aber was ich wieder nicht verstehe, warum muss man den "in" returnen? Ist das wirklich nötig? Und warum (also jetzt bei cin)?
    Also es funktioniert eigentlich wie es gedacht war, aber perfekt ist das ja wohl nicht oder?

    Und wenn ich das so mache wie Konrad Rudolph gesagt hat dann geht das bei mir aber nicht. Da passiert nichts das läuft einfach durch. Ohne das n cursor kommt oder sowas. Und was genau soll ich da jetzt überprüfen (siehe diese Zeile: if (not in >> temp) return in; was bewirkt die den genau). Hier mal der Code:

    #include <iostream>
    using namespace std;
    
    class math
    {
        public:
        math();
        void SetZahl(int a) {Zahl=a;}
        int GetZahl() {return Zahl;}
        private:
        int Zahl;
    };
    math::math()
    {
    
    }
    istream& operator >>(istream& in, math& object);
    int main()
    {
        math A;
        cin>>A;
    
        return 0;
    }
    istream& operator >>(istream& in, math& object)
    {
        int temp;
        if (not in >> temp) return in; // Fehler beim Einlesen.
        object.SetZahl(temp);
        return in;                     // Stream zurückgeben.
    }
    

    Bitte klärt mich auf. Dankeschön schon mal im Voraus.



  • Stromberg schrieb:

    Aber was ich wieder nicht verstehe, warum muss man den "in" returnen? Ist das wirklich nötig? Und warum (also jetzt bei cin)?

    Na, weil Du Einlese-Operationen verketten kannst. Du kannst doch schreiben 'cin >> a >> b'. Ob das empfehlenswert ist, sei mal dahingestellt. Für diese Verkettung muss der Stream im ersten Operator zurückgegeben werden.

    Stromberg schrieb:

    Und wenn ich das so mache wie Konrad Rudolph gesagt hat dann geht das bei mir aber nicht.

    Ja, ich habe vergessen, dass der Zustand ja auch 'eof' sein kann. Änder den Einlese-Code folgendermaßen ab, dann geht er:

    istream& operator >>(istream& in, math& object)
    {
        int temp;
        if ((in >> temp).fail()) return in; // Fehler beim Einlesen.
        object.SetZahl(temp);
        return in;                          // Stream zurückgeben.
    }
    

    Dieser Code hat, wie gesagt, zwei Vorteile vor Deinem:

    • Er testet, ob die Eingabe korrekt abgelaufen ist.
    • Er gibt den Stream zurück, sodass man Eingaben verketten kann.


  • Wie meinst du das ob die Einagebe korrekt abgelaufen ist? Wenn "cin" verwendet wird, und ich dann in der Konsole irgendwas eintippe, was soll den dann da nicht korrektablaufen? Und kannst du mir die Zeile hier mal erklären: if ((in >> temp).fail()) return in; was bewirkt den genau fail()? Und was soll der Punkt zwischen (in>>temp) und fail()?
    Dankeschön schon mal im Voraus.



  • Stromberg schrieb:

    Wie meinst du das ob die Einagebe korrekt abgelaufen ist? Wenn "cin" verwendet wird, und ich dann in der Konsole irgendwas eintippe, was soll den dann da nicht korrektablaufen? Und kannst du mir die Zeile hier mal erklären: if ((in >> temp).fail()) return in; was bewirkt den genau fail()? Und was soll der Punkt zwischen (in>>temp) und fail()?

    Na, ich sagte doch, dass '>>' einen Stream zurückliefert. Das bedeutet, ich kann auch seine Member-Funktionen aufrufen. '(in >> x).fail()' tut genau das: Es ruft erst op>> auf und anschließend 'fail()' -- und zwar auf den Rückgabewert der op>>-Operation. D.h. ich schaue, ob der Stream sich in einem korrekten Zustand befindet oder ob die Eingabe fehlerhaft war.

    Zur Frage "Was sollte da nicht korrekt ablaufen": Du könntest Mist eintippen. z.B. indem Du keine Zahl eintippst sondern ein Wort. Außerdem muss die Eingabe ja nicht immer von der Konsole aus stattfinden sondern könnte z.B. aus einer Datei erfolgen. Und was ist, wenn während des Einlesens die Datei plötzlich gelöscht wird? Dann schlägt die Eingabe schief.


Log in to reply