wake-up-neo.com

Operatorüberladung: Mitgliedsfunktion vs. Nicht-Mitgliedsfunktion?

Ich habe gelesen, dass ein überladener Operator, der als Elementfunktion deklariert wurde, asymmetrisch ist, weil er nur einen Parameter haben kann und der andere Parameter, der automatisch übergeben wird, der Zeiger this ist. Es gibt also keinen Standard, um sie zu vergleichen. Andererseits ist der als friend deklarierte überladene Operator symmetrisch, weil wir zwei Argumente desselben Typs übergeben und sie daher verglichen werden können.

Meine Frage ist, wenn ich den Wert eines Zeigers immer noch mit einer Referenz vergleichen kann, warum werden Freunde bevorzugt? (Bei Verwendung einer asymmetrischen Version werden dieselben Ergebnisse wie bei einer symmetrischen Version erzielt.) Warum verwenden STL-Algorithmen nur symmetrische Versionen?

105
badmaash

Wenn Sie Ihre überladene Operatorfunktion als Elementfunktion definieren, übersetzt der Compiler Ausdrücke wie s1 + s2 In s1.operator+(s2). Das heißt, die vom Operator überladene Member-Funktion wird beim ersten Operanden aufgerufen. So funktionieren Member-Funktionen!

Was aber, wenn der erste Operand keine Klasse ist? Es gibt ein großes Problem, wenn wir einen Operator überladen möchten, bei dem der erste Operand kein Klassentyp ist, sondern double. Also Sie kann nicht so schreiben 10.0 + s2. Sie können jedoch eine überladene Elementfunktion für Ausdrücke wie s1 + 10.0 Schreiben.

Um dieses ordering Problem zu lösen, definieren wir die überladene Operatorfunktion als friend WENN sie auf private Mitglieder zugreifen muss. Machen Sie es friend NUR, wenn es auf private Mitglieder zugreifen muss. Andernfalls machen Sie es einfach non- Freund Nicht-Mitglied Funktion zu verbessern Kapselung!

class Sample
{
 public:
    Sample operator + (const Sample& op2); //works with s1 + s2
    Sample operator + (double op2); //works with s1 + 10.0

   //Make it `friend` only when it needs to access private members. 
   //Otherwise simply make it **non-friend non-member** function.
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}

Lese das :
Ein kleines Problem bei der Reihenfolge in Operanden
Wie Nicht-Member-Funktionen die Verkapselung verbessern

134
Nawaz

Es ist nicht unbedingt eine Unterscheidung zwischen friend Operatorüberladungen und Überladungen von Mitgliedsfunktionsoperatoren, da es sich um global Operatorüberladungen und Überladungen von Mitgliedsfunktionsoperatoren handelt.

Ein Grund für die Bevorzugung einer globalen Operatorüberladung besteht darin, Ausdrücke zuzulassen, bei denen der Klassentyp auf der rechten Seite eines Binäroperators angezeigt wird. Beispielsweise:

Foo f = 100;
int x = 10;
cout << x + f;

Dies funktioniert nur, wenn eine globale Operatorüberladung für vorliegt

Foo-Operator + (int x, const Foo & f);

Beachten Sie, dass die globale Operatorüberladung nicht unbedingt eine friend -Funktion sein muss. Dies ist nur erforderlich, wenn Zugriff auf private Mitglieder von Foo erforderlich ist. Dies ist jedoch nicht immer der Fall.

Unabhängig davon, ob Foo nur eine Überladung eines Mitgliedsfunktionsoperators hatte, wie:

class Foo
{
  ...
  Foo operator + (int x);
  ...
};

... dann könnten wir nur Ausdrücke haben, bei denen eine Foo -Instanz auf dem links des Plus-Operators erscheint.

18
Charles Salvia