Operator überladen



  • Moin,

    Ich hab ein Problem mit einem Beispiel in meinem Buch!

    In dem Kapitel geht es darum wie man Operatoren Überlädt, und die Ausgabe von dem Autor stimmt nicht mit der, von mir überein und ich finde den fehler, nicht, allerdings finde ich die Ausgabe des Autors auch ein wenig seltsam!

    #include <iostream>
    using namespace std;
    
    class Counter
    {
    
    public:
           Counter();
           Counter(int initValue);
           ~Counter() {}
           int GetItsVal() const
           {
               return itsVal;
           }
    
           void SetItsVal(int x)
           {
                itsVal=x;
           }
    
           const Counter& operator++ ();
           const Counter operator++ (int);
    
    private: int itsVal;
    };
    
    Counter::Counter():
                       itsVal(0)
                       {}
    
    const Counter& Counter::operator++()
    {
          ++itsVal;
          return *this;
          }
    
    const Counter Counter::operator++(int)
    {
          Counter temp(*this);
          ++itsVal;
          return temp;
          }
    
           int main()
           {
    
           Counter i;
           cout << "Wert von i: " << i.GetItsVal()<< endl;
           i++;
           cout << "Wert von i: " << i.GetItsVal()<< endl;
           ++i;
           cout << "Wert von i: " << i.GetItsVal()<< endl;
           Counter a = ++i;
           cout << "Wert von a: " << a.GetItsVal();
           cout << " und von i: " << i.GetItsVal()<< endl;
           a = i++;
           cout << "Wert von a: " << a.GetItsVal();
           cout << " und von i: " << i.GetItsVal()<< endl;
    
               system("PAUSE");
               return 0;
           }
    

    Das kommt bei mir raus:

    Wert von i: 0
    Wert von i: 1
    Wert von i: 2
    Wert von a: 3 und von i: 3
    Wert von a: 3 und von i: 4

    Beim Autor kommt das:

    Wert von i: 0
    Wert von i: 1
    Wert von i: 2
    Wert von a: 3 und von i: 3
    Wert von a: 4 und von i: 4

    Habe ich etwas übersehen/falsch gemacht?

    Desweiteren ist in dem Zusammenhang leider nichts zum *this Zeiger gesagt worden, der wurde im Buch überhaupt nur einmal kurz erwähnt, und ich kann nicht ganz verstehen was genau dort passiert.

    Falls jemand Zeit hat würde ich mich freuen, wen mir jemand die beiden code teile in der der Operator geschrieben wird detailiert erklären könnte.

    Ansonsten würde ich mich auch über ein tutorial zu dem Thema freuen!

    Gruß und vielen dank im voraus!

    Muffin



  • Dein Ergebnis ist richtig, das aus dem Buch nicht.

    Der this-Pointer zeigt auf das Objekt, dessen Methode gerade abgearbeitet wird. Im Fall das operator++(int) erstellst du also eine Kopie von diesem Objekt, veränderst das Objekt und gibst die unveränderte Kopie zurück.



  • Ah, jetzt hab ichs verstanden, vielen dank 🙂 !



  • Ich habe nochmal eine Frage zum Überladen von Operatoren!

    Wen ich einen Operator habe wie +, nimmt er dann immer automatisch das linke objekt mit in die funktion? (ich weiß jetzt nicht so recht wie man das richtig umschreibt)

    Beispiel:
    a + b

    hierbei ist es doch so das this immer auf a zeigt oder?

    In meinem Buch wird unter anderem der ++ Operator überladen.

    const Counter Counter::operator ++ (int)
    {
    Counter temp(*this);
    ++itsVal;
    return temp;
    }
    
    const Counter& Counter::operator++()
    {
    ++itsVal;
    return *this;
    }
    

    Mein verständnis problem dabei ist, woher weiß der compiler wann etwas auf welcher seite steht.

    Wen es so richtig is wie ich es oben beschrieben habe würde bei "++a "ja der funktion kein paremter übergeben werden, da ja nichts auf der linken seite des operators ist.

    Und bei "a++" würde a übergeben werden und das würde dann die "geflaggte" version des operators aufrufen.
    Stimmt das so oder hab ich das falsch verstanden?

    Dann noch eine frage zum "=" Operator

    CAT &CAT::operator=(const CAT &rhs)
    {
    if(*this == rhs)
    { return *this; }
    delete itsWeight;
    delete itsAge;
    itsWeight = new int;
    itsAge= new int;
    *itsAge = rhs.GetAge();
    *itsWeight = rhs.GetWeight();
    return *this;
    }
    

    Nun zu meiner frage:

    Wen ich es richtig verstanden habe, wird mit delete itsWeight/itsAge der speicher freigegeben. Dann bekommen itsWeight/itsAge speicher auf dem heap reserviert, danach wird ihnen der wert von rhs.GetAge/GetWeight zugewiesen.

    und dann.. return *this. Wozu genau ist das, ich würde meinen das die Werte ja bereits ausgetauscht sind, wohin wird *this zurück gegebn?

    Gruß



  • Wen ich es richtig verstanden habe, wird mit delete itsWeight/itsAge der speicher freigegeben. Dann bekommen itsWeight/itsAge speicher auf dem heap reserviert, danach wird ihnen der wert von rhs.GetAge/GetWeight zugewiesen.

    its... sind Zeiger, die auf den Speicherbereich zeigen. Man muss delete anwenden (Speicher freigeben), bevor man diesen Zeigern neue Werte zuordnet! Ansonsten gibt es unausweichlich ein "memory leak".

    return *this. Wozu genau ist das, ich würde meinen das die Werte ja bereits ausgetauscht sind, wohin wird *this zurück gegebn?

    Schau Dir den Rückgabewert der Member-Funktion op= an. Das ist eine Referenz auf ein Objekt CAT. Es sollte der Inhalt von this, also das Objekt selbst zurückgegeben werden. Sonst geht so etwas nicht:

    CAT a = b = c = d;
    
    if(*this == rhs)
    { return *this; }
    

    ist sehr wichtig, weil es vor Selbstzuweisung schützt. Ansonsten würde man its... ungültig machen, um es anschließend sich selbst wieder zuzuordnen. Das ist wie ein Gedächtnisverlust des Objektes? => Bumm! 😃



  • Hehe ok, das war ne schwere Geburt 🙂 Damit hab ich mich seit 2 tagen rum geschlagen, aber nun hab ichs glaub ich auch verstanden.

    vielen dank für die Hilfe 🙂

    Gruß


Anmelden zum Antworten