Operatorüberladung - Als Methode oder als globale Funktion ?



  • Hi,
    Also ich will eigentlich nur sicher gehen, ob das was ich denke stimmt.

    Wenn man einen binären Operator hat, UND dieser Operator kommutativ ist (z.B. "+") dann sollte man diesen Operator als globale Funktion überladen. Der Grund liegt darin, dass evtl z.B. ein elementarer Datentyp durch einen Konvertierungskonstruktor implizit in ein Objekt der gewünschten Klasse konvertiert wird. Dies geht dann aber nur immer korrekt bei einer globalen Funktion
    Bsp:

    class X {
      int x;
      public:  
      X(int xx) : x(xx) {}
      friend X operator+ (const X&, const X&);
    };
    
    X operator+ (const X& a, const X& b) 
    {
       return X(a.x + b.x);
    }
    
    // irgendwo in main
    X x1(3);
    x1 + x1;  // Ok, sowohl für Member- als auch für globale Funktion
    x1 + 5;  // Auch ok, sowohl für Member-als auch für global Funktion
    5 + x1;  // nur für globale Funktion OK, aber nicht für Memberfunktion
    

    D.h. als Schlussfolgerung sollte man am besten alle binären Operatoren global überladen, richtig ?

    Den Zuweisungsoperator darf man sowieso nur als Membermethode überladen (weil ja ein L-Value erwartet wird)

    Und bei unären Operatoren ist es im Prinzip egal, ob nun global oder als Methode.Kommt beides eigtl aufs selbe raus.

    Stimmt das alles so, wie ich es geschrieben habe ?

    Stream-Klassen (also z.B. ostream) muss man als globale Funktion überladen, habe ich mal irgendwo gehört, und das stimmt ja soweit ich weiß auch. Warum eigentlich ?

    Ich hoffe mir kann da jemand was dazu sagen, danke.



  • Die Streamoperatoren (nicht Klassen) muss man deshalb global überladen, weil man keinen Zugriff auf die Klassendefinition von ios oder ostream oder was auch immer hat.

    Am praktischsten ist es übrigens (in den meisten Fällen), wenn man in der Klasse einen += Operator überlädt und dann der eigentliche Operator so aussieht:

    X operator+ (const X& l, const X& r)
    {
        X tmp (l);
        return tmp += r;
    }
    

    Sonst kann man es eventuell (bei komplizierteren Konstrukten) mit unvollständig ausgeführten Konstruktoren zu tun haben.

    Bei unären Operatoren mein ich gehört zu haben, dass sie grundsätzlich in der Klasse selbst überladen werden sollten.

    Das hier ist auch ganz praktisch: http://boost.org/libs/utility/operators.htm


Anmelden zum Antworten