2 Objekte miteinander vergleichen


  • Mod

    net schrieb:

    oder ihr machts ganz einfach:

    if (0 == memcmp (&p1, &p2, sizeof(Point)))
    {
       // objekte sind identisch
    }
    

    das würde ich nicht als einfacher bezeichnen. im übrigen ist das auch kein standard c+++ mehr. zum einen, weil Point kein POD ist. zum anderen, weil memcmp die "objektrepräsentation" vergleicht, und somit falsche negative entstehen können (weil du z.b. paddingbytes miteinander vergleichst).


  • Mod

    brainwave81 schrieb:

    die 2 var. müsste eigentlich auch gehen, bekomme aber ein kompiler error:
    "Unzulaessiger Aufruf einer nichtstatischen Member-Funktion"

    wer hat dir gesagt, das das geht. eine nicht statische methode, kann nur per . oder -> aufgerufen werden. womit sich die frage auch selbst beantwortet:
    um die gewünschte syntax zu erhalten, muss die betreffende funktion statisch sein (damit entfällt nat. die erste aufrufmethode - es hindert dich allerdings niemand daran, die funktion statisch und nicht statisch zu überladen). im übrigen existiert für so etwas der operator ==, es bietet sich also an, diesen direkt zu implementieren (bei benutzung der üblichen operatorsyntax spielt es keine rolle, ob der betreffende operator als memberfunktion oder namespace funktion implementiert ist).
    also als memberfunktion:

    bool operator==(const Point& rhs) const
    {
         return x == p_2.x && y == p_2.y;
    }
    

    oder als freie funktion (das ist - schon aus symmetriegründen - im allgemeinen vorzuziehen)

    class Point  
    {
    // ....
        friend bool operator==(const Point& lhs, const Point& rhs)
        {
            return lhs.x == rhs.x && lhs.y == rhs.y;
        }
    

    und weils so schön ist und wir einmal dabei sind, sollten wir auch noch operator != implementieren:

    bool operator!=(const Point& lhs, const Point& rhs)
    {
        return !( lhs == rhs );
    }
    


  • camper schrieb:

    ...weil memcmp die "objektrepräsentation" vergleicht, und somit falsche negative entstehen können (weil du z.b. paddingbytes miteinander vergleichst).

    das ist ein gutes argument. also vergesst meinen vorschlag...



  • also ich wollte es eigentlich nicht mit überladene operatoren machen..gibt es da keine andere lösung?



  • Wieso nicht? Genau aus diesem Grund kann man Operatoren überladen.
    Aber du kannst es auch ein wenig C#-Like machen, die überschreiben für sowas die geerbte Methode Equals:

    bool Equals(const Point& rhs) const
    {
         return x == rhs.x && y == rhs.y;
    }
    

    Edit:
    Oder als Friend:

    friend bool Equals(const Point& lhs, const Point& rhs)
    {
         return lhs.x == rhs.x && lhs.y == rhs.y;
    }
    

    Egal welche Variante, ich finde beide total unschön.



  • ok ich habe die variante hier genommen:

    class Point { 
    bool equal(Point const& obj) const { 
        if(x == obj.x && y == obj.y) return true; 
        return false; 
    }
    

    jetzt eine andere sache..wieso wird hier das objekt als referenz übernommen?

    danke leute!



  • Du brauchst darauf nur lesend zugreifen und ein Objekt kann man an eine Funktion eigentlich schneller als Referenz übergeben statt das ganze Objekt zu kopieren.



  • ah ja, aslo muss man das nicht unbedingt so machen, ausser das es const sein sollte..



  • Mit dem const zeigst du das du die Referenz nicht veränderst. Außerdem kannst du so auch ein konstantes Point Objekt an die Funktion übergeben, was sonst nicht funktionieren würde (und das ist wohl das wichtigste dabei). Wenn man Objekte nicht verändern muss, ist es in der Regel gut den Parameter als konstante Referenz anzugeben.
    Und falls du mit deiner Aussage meinst das man keine Referenz benutzen muss, solltest du es tun. Es bringt eigentlich nichts ein Objekt zu kopieren wenn man es nur lesend verwendet.



  • bringt eigentlich nichts ein Objekt zu kopieren wenn man es nur lesend verwendet.

    da hast du recht..danke jetzt weiss ich bescheid..



  • camper schrieb:

    also als memberfunktion:

    bool operator==(const Point& rhs) const
    {
         return x == p_2.x && y == p_2.y;
    }
    

    oder als freie funktion (das ist - schon aus symmetriegründen - im allgemeinen vorzuziehen)

    class Point  
    {
    // ....
        friend bool operator==(const Point& lhs, const Point& rhs)
        {
            return lhs.x == rhs.x && lhs.y == rhs.y;
        }
    

    was ist denn der vorteil der zweiten Variante?? Oder findest du sie einfach nur schöner??



  • wie gesagt, wollte ich noch keine überladene operatoren anwenden..



  • ist ja auch nur ne frage an camper... einfach aus Interesse



  • Dommel schrieb:

    was ist denn der vorteil der zweiten Variante?? Oder findest du sie einfach nur schöner??

    Man sollte eigentlich immer die zweite wählen denn:

    class Foo{
    public:
      Foo(){}
      Foo(int){}
    
      bool operator==(const Foo&){}
    };
    
    int main(){
      Foo a,b;
      a == b; // geht
      a == 2; // geht
      // 2 == a; geht nicht
    }
    


  • stimmt, mit der anderen Variante würde das wohl gehen...

    Implementiert man den Operator dann innerhalb oder außerhalb der Klassendeklaration??

    edit: Würde das den wirklich nicht gehen. Es wird doch für die 2 ein temporäres Objekt erzeugt und von dem könnte man doch den Operator aufrufen, oder?



  • Da er kein Mitglied der Klasse ist natürlich ausserhalb. Innerhalb kannst Du ihn nur friend deklarieren um auf private Member der Objekte zuzugreifen.



  • Oder auch als firend + inline in der Klasse.

    class Foo{
    public:
      friend void operator==(const Foo&, const Foo&){ /*...*/ }
    };
    

    Bei trivialen Vergleichen wie hier bevorzuge ich die Variante.

    Würde das den wirklich nicht gehen. Es wird doch für die 2 ein temporäres Objekt erzeugt und von dem könnte man doch den Operator aufrufen, oder?

    Das temporäre Objekt wird im Zuge eines impliciten Casts erzeugt. Die Regeln wann das passiert sind recht komplex allerdings sind sie hier nicht wichtig da sie sich nur auf Argumente beziehen. Allerdings ist "a" in "a == b" im Falle eines Member "=="-Operator kein Argument und folglich kann auch kein temporäres Objekt durch einen impliciten Cast erzeugt werden.


Anmelden zum Antworten