2009-08-17 5 views
2

Ich habe eine Struktur, für die ich eine relative Reihenfolge definieren möchte, indem ich <,>, < = und> = Operatoren definiere. tatsächlich in meiner Reihenfolge wird es keine Gleichheit geben, wenn also eine Struktur nicht kleiner als eine andere ist, ist sie automatisch größer.Wie wird in einem überladenen Operator auf die aktuelle Struktur verwiesen?

ich den ersten Operator wie folgt definiert:

struct MyStruct{ 
... 
... 

bool operator < (const MyStruct &b) const {return (somefancycomputation);} 

}; 

nun die anderen Betreiber ich möchte auf diesem Operator, so dass < = das gleiche wie < und die beiden anderen wird einfach zurückkehren basierend definieren das Gegenstück zurückgeben. so zum Beispiel für den Operator> Ich mag würde so etwas wie

bool operator > (const MyStruct &b) const {return !(self<b);} 

schreiben, aber ich weiß nicht, wie man diesen ‚Selbst‘ refere, da ich nur auf die Felder in der aktuellen Struktur refere kann.

Ganze ist in C++

hoffe, meine Frage war verständlich :)

danke für die Hilfe!

+2

Sind Sie sicher, dass Sie möchten, dass <<= 'das gleiche wie' <'zurückgibt? Ich würde normalerweise dagegen empfehlen. Wenn "a <= b" identisch mit "! (B b" identisch mit "b

+4

Normalerweise definiert man binäre Operatoren als freie Funktionen und nicht als Mitglieder. Dies ermöglicht, das gleiche Verhalten für beide Argumente zu erhalten, wenn implizite Konvertierungen ins Spiel kommen; Implizite Konvertierungen auf der zweiten, aber nicht auf der ersten, sind störend. – AProgrammer

Antwort

10

Selbst ist *this.

Das heißt, this ist ein Zeiger auf das aktuelle Objekt, so dass Sie es dereferenzieren müssen, um das tatsächliche Objekt zu erhalten.

+1

@genesys Erweitern Sie Daves Punkt, Sie möchten Ihren Code als etwas wie "bool-Operator> (const MyStruct & b) schreiben const {return! ((* This) Glen

+1

Upvoted. Eine weitere Möglichkeit besteht darin, eine Funktion zu erstellen, die zwei gegebene Structs A und B vergleicht. – mcandre

1

Überladener Operator ist nur eine Member-Funktion, aber mit einer ausgefallenen Syntax. Sie können es explizit wie folgt aufrufen:


this->operator<(b); 

oder sich ein paar Haare speichern :) und bieten nur int compare(const MyStruct&) Funktionselement und verwenden, die in allen Drittvergleichsoperatoren.

+0

Ja, eine benannte Funktion bereitzustellen und sie wiederzuverwenden, ist ein viel besser lesbarer Ansatz. – sharptooth

1

Dies ist ein Zeiger auf Ihr aktuelles Objekt. Also (wie @Dave Hinton sagt) müsstest du es dereferenzieren. Aber, gibt eine weitere Option

zwei Optionen:

return !(*this<b) 

or 

return (!this->operator<(b)) 

Ja, die ersten ist ganz schöner.

1

tatsächlich in meiner Reihenfolge wird es keine Gleichheit geben, also wenn eine Struktur nicht kleiner als eine andere ist, ist es automatisch größer.

Das ist ein Problem. C++ - Operationen (und viele Algorithmen) erfordern eine strict weak ordering, was (unter anderem) bedeutet, dass x == x für jede x gilt. Ganz allgemein:

not (x < y) and not (y < x) 

impliziert

x == y 

für jede x und y. Mit anderen Worten: Sie müssen höchstwahrscheinlich eine Art von Gleichheit für Ihre Struktur definieren, um mit jedem konventionellen Algorithmus zu arbeiten.

+0

Viele Dinge werden immer noch funktionieren, mit einigen Vorbehalten. 'std :: sort' funktioniert, obwohl Sie natürlich keine Kontrolle über die Reihenfolge der" äquivalenten "Werte haben. Sie können zwar 'set' und' map' haben, aber natürlich, sobald Sie einen Wert haben, können Sie keinen "äquivalenten" Eintrag in der Sammlung platzieren (aber Sie könnten mit 'multiset' und' multimap'). Dinge wie 'find' und' equal_range' sind zum Scheitern verurteilt. –

+1

Eine Zeichenfolge * schwache * Ordnung, impliziert keine vollständige Ordnung, oder Äquivalenz (in der Reihenfolge) bedeutet nicht Gleichheit., Oder mit anderen Worten, nicht (x

+1

@Charles, bedeutet nicht "schwach", dass zwei Elemente in Bezug auf die Reihenfolge gleichwertig sein können? Ich denke, worüber du gesprochen hast, heißt "partielle Ordnung" und nicht "schwache Ordnung". –

6

Wenn Sie eine operator< mit der entsprechenden Logik bereitstellen (unabhängig davon, ob sie als freie Funktion implementiert ist oder nicht), können Sie die anderen Operatoren als freie Funktionen implementieren. Dies folgt der Regel der Bevorzugung von Nichtmitgliedern über Mitglieder, wo dies möglich ist, und die freien Funktionen werden dasselbe Verhalten w.r.t. Konvertierungen der linken und rechten Operanden, während Operatoren, die als Elementfunktionen implementiert sind, nicht.

z.B.

inline bool operator>(const MyStruct& a, const MyStruct&b) 
{ 
    return b < a; 
} 

inline bool operator<=(const MyStruct& a, const MyStruct&b) 
{ 
    return !(b < a); 
} 

inline bool operator>=(const MyStruct& a, const MyStruct&b) 
{ 
    return !(a < b); 
} 
+0

Ein weiterer Beitrag Ich hätte gerne 10 Stimmen zu geben ... Und ich möchte hinzufügen, dass 'operator <', ein binärer Operator, der beide Argumente die gleichen behandelt (es lässt sie in Ruhe), in der Regel sollte auch als Nichtmitglied umgesetzt werden. – sbi

+0

Vielen Dank für Ihre Antwort .. Es tut mir leid für die Frage noob, aber könnten Sie mir auch erklären, was genau ist der Unterschied von Nicht-Mitgliedern und Mitgliedern und warum die erste zu bevorzugen ?? Danke :) –

0

ich oben mit Tom/Dave bin, dass in dem direkten Weg, dies zu schreiben:

return !(*this<b); 

aber für mich die ausdrücklich klar Form:

return !operator<(b); 

und Tom : zurück! (this-> operator < (b)); scheint ein wenig albern.

Dieses wenig böse C-Präprozessor-Code (Ich habe auch eine bessere, aber mehr technische Template-Lösung):

#define CREATE_SYMETRIC_ORDINAL_OPERATORS(Type) \ 
int operator !=(Type X) {return !((*this)==X); } \ 
int operator <(Type X) {return !((*this)>=X); } \ 
int operator >=(Type X) {return (((*this)>X)||((*this)==X)); } \ 
int operator <=(Type X) {return (((*this)<X)||((*this)==X)); } 

automatisch alle Vergleichsoperatoren unter der Annahme definiert == und> definiert sind wie folgt:

class Comparable { 
    public: 
    int operator ==(Comparable B); 
    int operator >(Comparable B); 
    CREATE_SYMETRIC_OPERATORS(Comparable); 
}; 
Diese
+0

Dieser Satz von Makros gibt mir die Squicks ein bisschen, ich habe Angst. –

+0

Ja, ich mochte es auch nie und habe es durch eine einfache Vererbung aus einer Klasse ersetzt, die == und Elemental

+0

@Elemental: Sie können beide (Einfachheit und Geschwindigkeit) mit dem CRTP erhalten. Außerdem ist es wahrscheinlich besser, den Vergleich auf 'operator <()' zu stützen, da dies normalerweise der Fall ist ('std :: map',' std :: sort' usw.). Schließlich, IMO, ist es besser, das RHS-Argument pro const-Verweis zu nehmen, da der Optimierer das Kopieren eines teuren zu kopierenden Typs möglicherweise nicht verhindern kann. Da dies für einen Kommentar zu groß ist, füge ich meine eigene Antwort hinzu. – sbi

2

wird als eine leichte Verbesserung gegenüber Element's answer gemeint:

template< class Derived > 
class Comparable { 
    public: 
    bool operator !=(const Derived& rhs) const 
    {return !(static_cast<Derived&>(*this) == rhs); } 

    bool operator <(const Derived& rhs) const 
    {return rhs < static_cast<Derived&>(*this); } 

    bool operator >=(const Derived& rhs) const 
    {return !(static_cast<Derived&>(*this) < rhs); } 

    bool operator <=(const Derived& rhs) const 
    {return !(static_cast<Derived&>(*this) > rhs); } 
}; 

struct MyStruct : public Comparable<MyStruct> { 
    bool operator ==(const MyStruct & rhs) const 
    {return /* whatever */; } 

    bool operator <(const MyStruct & rhs) const 
    {return /* whatever */; } 
}; 
Verwandte Themen