81

Ich habe gelesen, dass ein überladener Operator, der als Member-Funktion deklariert wurde, asymmetrisch ist, weil er nur einen Parameter haben kann und der andere Parameter automatisch den 'This' -Zeiger übergeben wird. Es gibt also keinen Standard, um sie zu vergleichen. Auf der anderen Seite ist der überladene Operator, der als Freund deklariert wurde, symmetrisch, weil wir zwei Argumente des gleichen Typs übergeben und daher können sie verglichen werden. Meine Frage ist, dass, wenn ich den lvalue eines Zeigers mit einer Referenz vergleichen kann, warum sind Freunde bevorzugt? (Bei Verwendung einer asymmetrischen Version werden dieselben Ergebnisse erzielt wie bei symmetrischen Versionen) Warum verwenden STL-Algorithmen nur symmetrische Versionen?Operatorüberladung: Member-Funktion vs. Nicht-Member-Funktion?

+9

Ihre Frage ist wirklich nur um binäre Operatoren. Nicht alle überladenen Operatoren sind auf einen einzelnen Parameter beschränkt. Der Operator() kann eine beliebige Anzahl von Parametern annehmen. Unäre Operatoren können dagegen keine Parameter haben. –

+1

http://stackoverflow.com/a/4421729/103167 –

+2

Dies ist eines von vielen Themen in dem überdachten [C++ FAQ: Betreiber Überlastung] (http://stackoverflow.com/questions/4421706/operator-overloading) –

Antwort

101

Wenn Sie Ihre Operatorüberladene Funktion als Elementfunktion definieren, übersetzt der Compiler Ausdrücke wie s1 + s2 in s1.operator+(s2). Das bedeutet, dass die überladene Mitgliedsfunktion des Operators auf dem ersten Operanden aufgerufen wird. So funktionieren Mitgliederfunktionen!

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

diese Bestellung Problem zu lösen, definieren wir Betreiber überladene Funktion als friend IF es private Mitglieder zugreifen muss. Machen Sie es nur friend, wenn es auf private Mitglieder zugreifen muss. Ansonsten einfach Nicht-Freund Nicht-Mitglied Funktion zu Verbesserung Verkapselung!

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 
} 

Lesen Sie diese:
A slight problem of ordering in operands
How Non-Member Functions Improve Encapsulation

+2

„Make' es friend' nur dann, wenn es privat members..and zugreifen muss, wenn Sie nicht über/gebohrt des Schreibens Accessoren, rechts – badmaash

+4

@Abhi: Wählen Sie Ihre Wahl: Verbesserte Encapsulation vs Faule Gewohnheit zu schreiben – Nawaz

+0

gibt es bekannte Fälle, in denen Sie mit dem globalen 'Operator +()' einfach sein 'return op2.operator + (op1) nicht nur das' friend' Stichwort vermeiden könnten; 'In beiden Fällen + standardmäßig würden den Eingangsabtastwert nicht ändern, und? stattdessen zurückgeben eine neue rvalue Instanz von 'Sample', nicht wahr? – matthias

14

Es ist nicht unbedingt eine Unterscheidung zwischen friend Betreiber Überlastungen und Memberfunktion Betreiber Überlastungen, wie es zwischen globalen Betreiber Überlastungen und Memberfunktion Betreiber Überlastung ist.

Ein Grund eine globalen Betreiber Überlastung zu bevorzugen ist, wenn Sie wollen Ausdrücke ermöglichen, wo der Klassentyp auf der Seite eines Binäroperators rechts erscheint. Zum Beispiel:

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

Dies funktioniert nur, wenn es eine globale Betreiber Überlastung ist für

Foo operator + (int x, const Foo & f);

Beachten Sie, dass die globale Bedienerüberlastung nicht notwendigerweise eine friend Funktion sein muss. Dies ist nur notwendig, wenn es Zugriff auf private Mitglieder von Foo benötigt, aber das ist nicht immer der Fall.

Unabhängig davon, ob Foo hatte nur einen Betreiber Überlastung Memberfunktion, wie:

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

... dann würden wir nur in der Lage sein, Ausdrücke zu haben, wo eine Foo Instanz auf den erscheint links des Plus Operator.

+1

+ 1 für die Unterscheidung zwischen Elementfunktionen und Dritt Funktionen machen anstatt Mitglied und Freund Funktionen. Ich denke heute würden wir sagen "Global oder Namespace Scope". –

Verwandte Themen