allgemeine fragen zur operatorüberladung



  • Hallo Leute,

    ich hab nich direkt ne frage, sondern brauche eher infos, damit ich die operatorüberladung verstehe:

    Könnt ihr mir erklären, wann ich operatorn in klassen überlade, wann ausserhalb?

    wann der operator eine referenz zurückgibt, wann nicht?

    meine fragen haben begonnen, bei folgenden code:

    class test
    {
     public:
      test(int number_one,int number_two){one=nubmer_one,two=number_two;}
      test operator*{const test& rhs)
      { 
       int resultOne = one*rhs.one;
       int resultTwo = two*rhs.two;
       test result(resultOne,resultTwo);
       return result;
      }
     private:
      int one;
      int two;
    };
    
    int main()
    {
     test t(10,20);
     test x(30,40);
     test y = t*x;
     return 0;
    }
    

    so, mein problem bei dem operator ist das:
    die Zeile

    test y=t*x;
    

    sagt mir das y ist t mal x!
    und das würde für mich bedeuten, das der operator 2 parameter aufnimmt, t und x!

    da das ja aber anscheinend falsch ist, frag ich euch, wie das mit dem überladen so richtig klappt!

    ich danke euch schonmal im voraus!



  • Normalerweise packst du es in die Klasse, außer:
    a) Du kannst die Klasse des linken Operanden nicht ändern (betrifft besonders die Ein/Ausgabe-Operatoren >> und <<)
    b) Du benötigst implizite Umwandlung für den linken Operanden (z.B. willst du bei einer eigenen Zahlen-Klasse auch "x=5*y;" zulassen)



  • Könnt ihr mir erklären, wann ich operatorn in klassen überlade, wann ausserhalb?

    Die gängige Regel ist: wann immer möglich, implementiere Operatoren als non-member. Ausnahmen sind die Operatoren = () [] und ->, die alle als Member implementiert werden müssen.
    Die zusammengestzen Zuweisungsoperatoren (+= -= *= /=) können als non-member implementiert werden. Normalerweise implementiert man sie aber als Member.

    einszweidrei schrieb:

    meine fragen haben begonnen, bei folgenden code:

    class test
    {
     public:
      test(int number_one,int number_two){one=nubmer_one,two=number_two;}
      test operator*{const test& rhs)
      { 
       int resultOne = one*rhs.one;
       int resultTwo = two*rhs.two;
       test result(resultOne,resultTwo);
       return result;
      }
     private:
      int one;
      int two;
    };
    
    int main()
    {
     test t(10,20);
     test x(30,40);
     test y = t*x;
     return 0;
    }
    

    so, mein problem bei dem operator ist das:
    die Zeile

    test y=t*x;
    

    sagt mir das y ist t mal x!
    und das würde für mich bedeuten, das der operator 2 parameter aufnimmt, t und x!

    Korrekt.

    da das ja aber anscheinend falsch ist, frag ich euch, wie das mit dem überladen so richtig klappt!

    Das ist nicht falsch und die von dir implementierte Überladung nimmt auch zwei Parameter entgegen. Da du den Operator* allerdings als Member implementiert hast ist der erste Parameter implizit. Es handelt sich hier um this.

    test y=t*x;
    

    Ist in diesem fall

    test y=t.operator*(x);
    

    rhs ist also x. t ist this in der Memberfunktion.



  • CStoll schrieb:

    Normalerweise packst du es in die Klasse

    Das ist spätestens seit Scott Meyers' "How Non-Member Functions Improve Encapsulation" überholt.

    Herb Sutter schreibt in "Exceptional C++":

    The standard requires that operators = () [] and -> must be members, and class-specific operators new, new[], delete, and delete[] must be static members. For all other functions:

    if the function is operator>> or operator<< for stream I/O,
    or if it needs type conversions on its leftmost argument,
    or if it can be implemented using the class's public interface alone,

    make it a nonmember (and friend if needed in the first two cases)

    if it needs to behave virtually,

    add a virtual member function to provide the virtual behavior,
    and implement it in terms of that

    else
    make it a member.



  • ich danke euch erstmal, ein bisschen licht ist reingekommen!

    Nun noch die frage mit dem rückgabewert!

    Weil ich sehr oft verschiedene sehe!

    void operator<<
    ostream operator<<
    ostream& operator<<

    wie sieht es da aus(dieser operator is mir da nur eingefallen)
    auch bei eigenen klasse, wann weiß ich, das ein operator eine referenz oder eine kopie zurückgibt?



  • einszweidrei schrieb:

    ich danke euch erstmal, ein bisschen licht ist reingekommen!

    Nun noch die frage mit dem rückgabewert!

    Weil ich sehr oft verschiedene sehe!

    void operator<<
    ostream operator<<
    ostream& operator<<

    wie sieht es da aus(dieser operator is mir da nur eingefallen)

    Die erste Variante ist käse, da sie keine Verkettung zulässt (sowas wie cout << foo << bar << foobar). Die zweite Variante ist kein gültiges C++, da ostream keinen öffentlichen Copy-Ctor hat (der für die by-value Rückgabe nötig wäre). Die dritte Variante ist korrekt.

    auch bei eigenen klasse, wann weiß ich, das ein operator eine referenz oder eine kopie zurückgibt?

    Referenz wenn möglich, Kopie wenn nötig.

    Beispiel: Operatoren wie += können eine Referenz liefern, da sie auf einem vorhandenen Objekt aufgerufen werden und dieses verändern. Du hast also vorher bereits ein Objekt, welches du dann auch als Ergebnis zurückliefern kannst.

    Operatoren wie + hingegen müssen ein neues Objekt erzeugen ( 7 + 3 verändert werden 7 noch drei sondern erzeugt ein neues Objekt mit dem Wert zehn). Da das Objekt innerhalb des Operators erzeugt werden muss kannst du hier aber keine Referenz liefern, da diese ja nach Ablauf des Operators ungültig werden würde (das lokale Objekt wird mit Verlassen des Operators zerstört). In diesem Fall bleibt dir also nur eine Kopie.



  • aha, naja ich werde da mal bisschen probieren, und wenn ich weiter fragen habe, stelle ich die!

    Danke erstmal! 🙂



  • mal so ne vermutung, die alles erheblich vereinfachen könnte, wenn sie kein unfug ist:

    falls man so ein konzept wie "subjekt" kennt. also die sorte objekt, die in deutschen aussagesätzen vor dem verb steht. die sorte von objekt im nominativ, die immer im satz ist. die sorte von objekt, die man in prolog als ersten parameter schreiben sollte.
    so ein subjekt wird über this übergeben. alles andere nicht. gibts zwei subjekte, gibts in wirklichkeit keins.


Anmelden zum Antworten