Problem mit Relation-Überladung



  • Hallo,

    folgendes Problem, um die Größe 2 Ascii-Bilder anhand ihrer Reihenanzahl vergleichen zu können möchte ich eine Relation wie ">" überladen.

    Meine Klasse besitzt bereits eine Funktion zum Auslesen der Zeilenanzahl:

    size_type get_row()const{return lines.size();}
    

    Laut Dozent soll man eine Relationen so überladen:

    inline bool operator> (const X& lhs, const X& rhs) {return operator< (rhs,lhs);}
    

    für meine Klasse habe ich diese Funktion daraus folgend so deklariert:

    inline bool operator> (const AsciiPicture& lhs, const AsciiPicture& rhs);
    

    Und in meiner CPP-Datei, welche die Klassse includiert die Funktion folgt definiert:

    bool AsciiPicture::operator> (const AsciiPicture& lhs, const AsciiPicture& rhs) 
    {
    	return operator< (rhs->lines.size(), lhs->lines.size());
    }
    

    Ansich erscheint das für mich als logisch, jedoch bekomme ich dann die Fehlermeldung, das schon die Deklaration in der Klasse, welche ja eine binäre Relation ist, zuviele Parameter enthält.. jedoch habe ich nur rhs und lhs.

    nach einingen rumprobieren habe ich rausgefunden, dass wenn ich die Deklaration statt "inline" als "friend" mache dieses Problem nicht mehr auftritt.. jedoch bekomme ich dann sehr viele Probleme mit meiner Definition in der CPP-Datei..

    los gehts mit:

    error C2039: '>' : is not a member of 'AsciiPicture'

    error C2819: type 'AsciiPicture' does not have an overloaded member 'operator ->' : see declaration of 'AsciiPicture' did you intend to use '.' instead?

    error C2232: '->AsciiPicture::lines' : left operand has 'class' type, use '.'

    error C2228: left of '.size' must have class/struct/union

    usw.. und sofort 😕

    Wo liegt der Fehler? Ich kanns einfach nicht finden..

    Vielen Dank schonmal..



  • travelflo22 schrieb:

    Ansich erscheint das für mich als logisch, jedoch bekomme ich dann die Fehlermeldung, das schon die Deklaration in der Klasse, welche ja eine binäre Relation ist, zuviele Parameter enthält.. jedoch habe ich nur rhs und lhs.

    Wenn du die Funktion so deklarieren/definieren willt, musst du das außerhalb der Klassendefinition tun. Ansonsten darf der Operator nur ein Argument übernehmen, da der Operator sonst ja keine einfache Funktion, sondern eine Methode ist, deren erstes Argument automatisch die jeweilige Instanz ist.

    Außerdem hift es wahrscheinich nicht so viel, den größer Operator über den kleiner Operator zu implementieren, jedenfalls nur, wenn du den kleiner Operator schon überladen hast 🙂

    Also entweder du machst es so:

    class X
    {
        public:
        bool operator> (const X& rhs) {return operator< (rhs,*this);}
    };
    

    oder so:

    class X
    {
        //...
    };
    
    bool operator> (const X& lhs, const X& rhs) {return operator< (rhs,lhs);}
    

    Zustätzlich musst du dann natürlich noch den kleiner operator überladen, und zwar nicht indem du den größer Operator verwendest 🙂

    Felix :xmas2:


  • Mod

    travelflo22 schrieb:

    Laut Dozent soll man eine Relationen so überladen:

    inline bool operator> (const X& lhs, const X& rhs) {return operator< (rhs,lhs);}
    

    Das Zurückführen ist mit Sicherheit eine gute Idee, aber bei dieser Syntax ist es kein Wunder, wenn du Schwierigkeiten hast, das Konzept zu erkennen. Der Sinn von Operatorüberladung ist die Vereinfachung von Syntax. Wir definieren einen Operator x um schreiben zu können:
    a x b
    und nicht
    operator x(a,b)
    zumal beide nicht ganz äquivalent sind, denn Letzteres erzwingt die Implementation außerhalb der Klasse.

    Richtig also:

    inline bool operator> (const X& lhs, const X& rhs) {return rhs<lhs;}
    

    Der Operator wird also auf einen anderen Operator mit denselben Operanden zurückgeführt, nur dass diese Operanden vertauscht sind. Das ist das, was in deiner Implementation verlorengegangen ist. Damit eine solche Zurückführung möglich ist, muss dieser andere Operator natürlich ebenfalls existieren, den musst du also auch noch schreiben. Der Vorteil ist aber, dass nur einer dieser Operatoren tatsächlich etwas Interessantes macht. Alle anderen können dagegen rein schematisch implementiert werden, was der Korrektheit zugute kommt. Wenn du sicher bist, das der eine interessante Operator funktioniert, weißt du sofort, dass das auch für die anderen gilt.
    Es ist üblich, Relationen vom kleiner-als-Operator ausgehend zu implemnentieren. Zwingend ist das nicht, hat allerdings eine lange Tradition.

    Dein Compiler beschwert sich im Übrigen nicht darüber sondern über die Verwendung des -> Operators anstelle des Punkt-Operators, Ersterer ist für Pointer gedacht und müsste für Klassen erst überladen werden, was hier nicht sinnvoll sein dürfte.



  • Aber genau mit lsh und rsh, sprich 2 Paramtern funktioniert es nicht innerhalb der Klasse... das ist ja das Problem.. sollte ich es außerhalb der Klasse implementieren? Aber wie sieht dann die Deklaration aus? Weil dann deklariere ich wieder 2 Parameter und es geht wiederholt nicht... 🙄



  • Ich bin nun soweit gekommen:

    public:
    
    AsciiPicture();
    
    //Ermitteln der Anzahl der Zeilen
    size_type get_row()const{return lines.size();}
    
    inline bool operator < (const AsciiPicture& rhs)const
    	{
    		return rhs.get_row().operator < (*this.get_row());
    	}
    

    egibt 4 fehler:

    error C2228: left of '.<' must have class/struct/union type is 'AsciiPicture::size_type'

    error C2228: left of '.get_row' must have class/struct/union
    type is 'const AsciiPicture *const '
    did you intend to use '->' instead?

    und nochmal die 2 Fehler... dabei habe ich doch eingentlich soweit alles beachtet, was oben geschrieben wurde.. hmmmm 🙄



  • Das kommt halt davon wenn man elitär sein will.
    Der einfache Weg ist der bessere:

    bool operator < (const AsciiPicture& rhs)const
    {
       return getRow() < rhs.getRow();
    }
    


  • Danke...

    ps: ich will gar nichts sein 🕶

    Nur so ganz nachvollziehen kann iches noch nicht.. zum Verständnis.. Ich habe 2 Objekte der Klasse, da die Implementierung innerhalb der Klasse steht ist sie quasi schon das eine Objekt auf sich bezogen, und wird verglichen mit dem 2. Objekt namens rhs.. ist das korrekt so?



  • Exakt.


Anmelden zum Antworten