2 Objekte miteinander vergleichen
-
folgendes problem:
class Point { public: ... bool isident(Point,Point) { if (p_1.x == p_2.x && p_1.y == p_2.y) return true; else return false; } private: float x; float y; }; void main() { Point p1(1, 90); Point p2(3, 8); cout << p3.isident(p1, p2) << endl; //FUNKTIONIERT cout << Point::isident(p1, p2) << endl; //FUNKTIONIERT NICHT! }
will die 2 punkte miteinander vergleichen (p1 und p2).
sollen die koordinaten gleich sein return true, sonst false.
die erste variante geht..aber das ist kein guter stiel.
die 2 var. müsste eigentlich auch gehen, bekomme aber ein kompiler error:
"Unzulaessiger Aufruf einer nichtstatischen Member-Funktion"wie kann ich am besten die 2 objekte miteinander vergleichen?
-
Ich würd das eher so machen:
class Point { bool equal(Point const& obj) const { if(x == obj.x && y == obj.y) return true; return false; }
Dann kann operator == einfach equal aufrufen.
-
if(x == obj.x && y == obj.y) return true; return false;
ist doppelt gemoppelt
return( x == obj.x && y == obj.y );
-
oder ihr machts ganz einfach:
if (0 == memcmp (&p1, &p2, sizeof(Point))) { // objekte sind identisch }
-
net schrieb:
oder ihr machts ganz einfach:
if (0 == memcmp (&p1, &p2, sizeof(Point))) { // objekte sind identisch }
Solche Fricklerlösungen sind hier nicht erwünscht.
-
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).
-
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?