Vergleich von Objekten



  • Vielleicht habe ich nicht lange genug gesucht, aber sowohl im Forum als auch in Google fand ich nichts zum vergleich von Objekten mithilfe STL

    Ungefähr so möchte ich das haben

    template<typename T>
    bool compare(T objekt_1, T objekt_2);
    

    Und so möchte ich es nutzen:

    class MyClass
    {
    protected:
    
        int someInteger;
        bool someBool;
    
    public:
    
        MyClass(int value)
        {
            MyClass::someInteger = value;
            MyClass::someBool = true;
        }
    }
    
    int main(void)
    {
        bool result;
    
        // create two objects of class «MyClass»
        MyClass object1(2);
        MyClass object2(7);
    
        // compare objects 1 & 2
        result = compare<MyClass>(object1, object2);
    
        // result should be = false, cause the object are different
    
        // create another two objects of class «MyClass»
        MyClass object3(5);
        MyClass object4(5);
    
        // compare objects 3 & 4
        result = compare<MyClass>(object3, object4);
    
        // result should now be = true, cause the object are now equal
    }
    

    Gibt es überhaupt eine Möglichkeit ein solches Konstrukt zu realisieren?


  • Mod

    operator== ?
    std::equal_to ?
    Ich weiß nicht so genau, was du dir vorstellst und wieso du diese Lösungen nicht nutzt/gefunden hast.



  • Hi,

    normalerweise überschreibt man dafür einfach den operator==

    bool operator==(const MyClass& lhs, const MyClass& rhs)
    {
        return lhs.GetInteger() == rhs.GetInteger();
    }
    


  • Ja klar, dafür überlädt man den Vergleichsoperator, aber was wenn ich Objekte vergleichen möchte die ich in keinem Fall manipulieren kann, heißt dass ich MyClass zwar instanzieren, aber keinesfalls umschreiben kann, ich kann also keine Klassenoperatorüberladung beschreiben, muss aber die instanzierten Objekte irgendwie vergleichen, sind sie nun identisch oder nicht..

    wenn nicht mit STL, wie wäre es dann möglich?

    P.S. möglicherweise eine Art Binärvergleich dieser Objekte?



  • RussianTux schrieb:

    Ja klar, dafür überlädt man den Vergleichsoperator, aber was wenn ich Objekte vergleichen möchte die ich in keinem Fall manipulieren kann, heißt dass ich MyClass zwar instanzieren, aber keinesfalls umschreiben kann, ich kann also keine Klassenoperatorüberladung beschreiben, muss aber die instanzierten Objekte irgendwie vergleichen, sind sie nun identisch oder nicht..

    wenn nicht mit STL, wie wäre es dann möglich?

    Dann musst du die entsprechenden Funktionen eben const-qualifizieren. Oder was meinst du?



  • out schrieb:

    RussianTux schrieb:

    Ja klar, dafür überlädt man den Vergleichsoperator, aber was wenn ich Objekte vergleichen möchte die ich in keinem Fall manipulieren kann, heißt dass ich MyClass zwar instanzieren, aber keinesfalls umschreiben kann, ich kann also keine Klassenoperatorüberladung beschreiben, muss aber die instanzierten Objekte irgendwie vergleichen, sind sie nun identisch oder nicht..

    wenn nicht mit STL, wie wäre es dann möglich?

    Dann musst du die entsprechenden Funktionen eben const-qualifizieren. Oder was meinst du?

    Hmm wie meinst du das? Beispiel?



  • class MyClass
    {
    	private:
    		int i;
    	public:
    		MyClass(int i) : i(i) {}
    		int GetInteger() const
    		{
    			return i;
    		}
    };
    
    bool operator==(const MyClass& lhs, const MyClass& rhs)
    {
        return lhs.GetInteger() == rhs.GetInteger();
    } 
    
    int main()
    {
    	const MyClass is_const(2);
    	MyClass is_not_const(4);
    
    	if( is_const==is_const );
    	if( is_not_const==is_not_const );
    	if( is_not_const==is_const);
    }
    

    Wo ist das Problem?



  • out schrieb:

    class MyClass
    {
    	private:
    		int i;
    	public:
    		MyClass(int i) : i(i) {}
    		int GetInteger() const
    		{
    			return i;
    		}
    };
    
    bool operator==(const MyClass& lhs, const MyClass& rhs)
    {
        return lhs.GetInteger() == rhs.GetInteger();
    } 
    
    int main()
    {
    	const MyClass is_const(2);
    	MyClass is_not_const(4);
    
    	if( is_const==is_const );
    	if( is_not_const==is_not_const );
    	if( is_not_const==is_const);
    }
    

    Wo ist das Problem?

    Das Problem habe ich oben bereits erwähnt, ich kann die Klasse nicht manipulieren, muss aber 2 Instanzen dieser Klasse auf Gleichheit vergleichen.
    Außerdem kann anstelle dieser Klasse eine komplett andere stehen, die Instanzen welcher man auch vergleich können muss:

    bool result;
    
    SomeClass object1;
    SomeClass object2;
    
    result = compare<SomeClass>(object1, object2);
    
    int object3;
    int object4;
    
    result = compare<int>(object3, object4);
    
    AnotherClass object5;
    AnotherClass object6;
    
    result = compare<AnotherClass>(object5, object6);
    


  • Wieso sollte man denn überhaupt noch operator== überladen, wenn es die ultimative Vergleichsfunktion gäbe, die alles mit jedem vergleichen kann?

    Man schreibt operator== für jede Klasse neu, es gibt nicht einfach eine Funktion, die das, was Du willst, übernimmt.



  • Ok, also diese Klasse

    class MyClass
    {
    protected:
    
        int someInteger;
        bool someBool;
    
    public:
    
        MyClass(int value)
        {
            MyClass::someInteger = value;
            MyClass::someBool = true;
        }
    }
    

    ist fix und kann nicht geändert werden. Dann kommst du von außen auch nicht an die Attribute. D.h. du kannst zwei Instanzen diese Klasse nicht auf Gleichheit überprüfen.



  • Eisflamme schrieb:

    Wieso sollte man denn überhaupt noch operator== überladen, wenn es die ultimative Vergleichsfunktion gäbe, die alles mit jedem vergleichen kann?

    Man schreibt operator== für jede Klasse neu, es gibt nicht einfach eine Funktion, die das, was Du willst, übernimmt.

    Wenn es diese nicht gibt, wie wäre es möglich eine Funktion für diesen Fall der Anwendung zu schreiben?



  • Für welchen Fall denn? Deinen Fall habe ich eben verstanden als "ich will eine Funktion, die alles kann". Diesen kannst Du nicht lösen. Außer vielleicht mit memcmp.

    Wenn Du eine Klasse hast, deren Schnittstelle und Implementation Du nicht verändern kannst, dann kannst Du für diese Klasse einen globalen operator== gleich schreiben. Dieser muss aber auf die Attribute, welche als Vergleichskriterien dienen können, zugreifen können (z.B. über Getter), ansonsten ist kein Vergleich möglich, wie out es schon beschrieben hat.

    Diese globale Vergleichsfunktion habe ich beispielhaft ja in meinem ersten Post implementiert. Das ist Zusatzcode, der nicht in der Klasse stehen muss.

    Edit:
    Übrigens liegt ein Teil der Verwirrung der Antwortenden an deiner Formulierung, ich gehe Mal kurz drauf ein:

    Ja klar, dafür überlädt man den Vergleichsoperator, aber was wenn ich Objekte vergleichen möchte die ich in keinem Fall manipulieren kann,

    Objekte sind Instanzen. Wenn Du die nicht manipulieren kannst, heißt das, dass sie const sind, d.h. dass du deren Attribute nicht verändern kannst. Das meinst Du aber anscheinend nicht.

    heißt dass ich MyClass zwar instanzieren, aber keinesfalls umschreiben kann,

    Okay, also die Klasse ändern (manipulieren ist unüblich, das versteht man nicht sofort; umschreiben ist okay).

    ich kann also keine Klassenoperatorüberladung beschreiben,

    Auch komisch formuliert. Du kannst innerhalb der Klasse keine Operatoren überladen.

    Kleinigkeiten, aber wenn das alles korrekt beschrieben ist, kommt man schneller zu einer Lösung. Nur für die (nahe) Zukunft. 🙂



  • Ok, du könntest z.B. das machen:

    class MyClass
    {
    protected:
    
        int someInteger;
        bool someBool;
    
    public:
    
        MyClass(int value)
        {
            MyClass::someInteger = value;
            MyClass::someBool = true;
        }
    };
    
    class MyClass_Modified : private MyClass
    {
    public:
        MyClass_Modified(int value) : MyClass(value) {}
    	int GetInteger() const
        {
    		return someInteger;
        } 
    };
    bool operator==(const MyClass_Modified& lhs, const MyClass_Modified& rhs)
    {
        return lhs.GetInteger() == rhs.GetInteger();
    }
    
    int main()
    {
        const MyClass_Modified is_const(2);
        MyClass_Modified is_not_const(4);
    
        if( is_const==is_const );
        if( is_not_const==is_not_const );
        if( is_not_const==is_const);
    }
    

    Eine ultimative compare-Funktion bekommst du trotzdem nicht hin. Du kannst ja nicht davon aussgehen, dass jede Klasse dieselben Attribute hat.



  • Eisflamme schrieb:

    Für welchen Fall denn? Deinen Fall habe ich eben verstanden als "ich will eine Funktion, die alles kann". Diesen kannst Du nicht lösen. Außer vielleicht mit memcmp.

    memcmp wäre undefiniertes Verhalten.


  • Mod

    TyRoXx schrieb:

    memcmp wäre undefiniertes Verhalten.

    Nicht immer. Vielleicht kennt er ja die Klasseninterna und weiß, dass ein memcmp in Ordnung wäre. Außerdem wäre nicht das Verhalten von memcmp an sich undefiniert, sondern höchstens, ob das Ergebnis irgendetwas mit Gleichheit im üblichen Sinne zu tun hat oder nicht.



  • template <typename T>
    bool equalObjects(T object_1, T object_2)
    {
    	if (memcmp(&object_1, &object_2, sizeof(T)) == 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
    

    no comment



  • SeppJ schrieb:

    TyRoXx schrieb:

    memcmp wäre undefiniertes Verhalten.

    Nicht immer. Vielleicht kennt er ja die Klasseninterna und weiß, dass ein memcmp in Ordnung wäre. Außerdem wäre nicht das Verhalten von memcmp an sich undefiniert, sondern höchstens, ob das Ergebnis irgendetwas mit Gleichheit im üblichen Sinne zu tun hat oder nicht.

    Ich finde keinen Nachweis, aber der Zugriff auf private s eines Objektes riecht nach undefined behaviour.
    Das Ergebnis von memcmp auf Strukturen jeglicher Art ist mindestens implementation-defined, weil das Layout im Speicher nicht vorgegeben ist.

    Welchen Sinn soll es eigentlich haben, Objekte anhand nicht-zugänglicher Eigenschaften zu vergleichen?



  • RussianTux schrieb:

    template <typename T>
    bool equalObjects(T object_1, T object_2)
    {
    	if (memcmp(&object_1, &object_2, sizeof(T)) == 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
    

    no comment

    Es gibt natürlich wieder ein Problem bezüglich memcmp, es führt keine "deep comparison" aus, wenn das Object als pointer in sich trägt, die auf Daten zeigen , welche man auch vergleichen möchte, dann funktioniert das memcmp-Konstrukt nicht.

    Es wird stets ein "not equal" werfen, weil nicht mal die pointer adressen gleich sind...

    Ich habe hier noch eine weitere Idee auf Lager: Serialisierung und Vergleich des streams... aber wäre eine tiefe Serialisierung überhaupt möglich?

    was sagt ihr dazu?



  • RussianTux schrieb:

    template <typename T>
    bool equalObjects(T object_1, T object_2)
    {
    	if (memcmp(&object_1, &object_2, sizeof(T)) == 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
    

    no comment

    Was das für ein Hack. 😃

    http://www.codepolice.org/c/memcmp.html
    http://rxwen.blogspot.de/2009/12/use-memcmp-to-compare-objects.html



  • was sagt ihr dazu?

    Wieso wir? Ich habe bisher von keinem gelesen, der so eine Universallösung will. Nur du möchtest aus ungenannten Gründen so etwas haben.

    Ich sehe auch keinen wirklichen Sinn darin. Klassen können einen operator== anbieten, wenn es Sinn macht. Das hat auch den Vorteil, dass die Identität eines Objektes gleich mitbestimmt wird. Wenn kein operator== vorhanden ist, macht es evtl. auch keinen Sinn einen Vergleich durchzuführen (bzw. gibt es dann keine Standard-Vergleichskriterien). Dann würdest Du ohne genaue Kenntnis der Klasse einen Vergleichsoperator nutzen, dessen Ergebnis Du überhaupt nicht einschätzen könntest.

    Wenn ich Klassen nutze, die keinen operator== anbieten und ich einen will, beschäftige ich mich genau mit der Klasse und schreibe einen. Das ist auch nicht weniger Arbeit als mich genau mit der Klasse zu beschäftigen und den Universal-operator== zu benutzen.

    Erklär doch lieber Mal, wofür Du so etwas brauchst. Mir scheint, dass das mehr ein Gedankenexperiment ist, als dass es einen tatsächlichen Anwendungsfall gibt.


Log in to reply