2010-05-05 9 views
9

Was ist der Unterschied zwischen dem Operatorüberladen mit dem Schlüsselwort friend und als Mitgliedfunktion innerhalb einer Klasse?Operatorüberladung (Freundes- und Mitgliedsfunktion)

Auch, was ist der Unterschied im Falle eines unären Operators überladen (d. H. Als Freund vs. als Mitglied-Funktion)?

Antwort

12

Jacob ist korrekt ... eine friend Funktion, die innerhalb einer Klasse deklariert wurde, hat Zugriff auf diese Klasse, aber sie ist nicht innerhalb der Klasse, und alle anderen haben Zugriff darauf.

Für eine Operatorüberladung, die kein Mitglied der Klasse ist (auch freie Funktion genannt, kann es ein Freund sein, oder vielleicht nicht), sind die Argumente die gleichen wie die Operanden. Für einen, der Mitglied einer Klasse ist, ist der erste Operand das "implizite Argument", das this wird.

Die implizite Argument unterscheidet sich von dem ersten Argument zu einer freien Funktion in ein paar Möglichkeiten:

  • Sein Typ ist Referenz-to-Klasse, während die freie Funktion jeder Art für das erste Argument erklären kann.
  • Es beteiligt sich nicht an der impliziten Typkonvertierung. (Es wird nicht von einem Konvertierungskonstruktor temporär initialisiert.)
  • Es nimmt an der virtuellen Override-Auflösung teil. (A virtual Überlast wird vom dynamischen Typ des ersten Operanden ausgewählt werden, die mit freien Funktionen ohne zusätzlichen Code nicht möglich ist.)

Die Situation ist das gleiche für unäre, binär oder n-ary (in der Fall von operator()).

Mitglieder Privileg Mutation: Operatoren, die den ersten Operanden ändern (zB +=, =, Präfix ++) als Member-Funktionen implementiert werden und sollten ausschließlich den Mut aller Überlastungen implementieren. Postfix ++ ist ein Bürger zweiter Klasse; Es ist implementiert als Obj ret = *this; ++ this; return ret;. Beachten Sie, dass dies manchmal für Kopierkonstruktoren gilt, die *this = initializer enthalten können.

Freiheitsregel für Pendler: Nur kommutative Operatoren (zB /) sollten freie Funktionen haben; alle anderen Operatoren (z. B. unäre Dinge) sollten Mitglieder sein. Kommutative Operatoren machen von Natur aus eine Kopie des Objekts; Sie sind als Obj ret = lhs; ret @= rhs; return ret; implementiert, wobei @ der kommutative Operator ist und lhs und rhs linksseitige und rechtsseitige Argumente sind.

Goldene Regel von C++ Freundschaft: vermeiden Freundschaft. friend verschmutzt die Semantik eines Entwurfs. Überladung: Überladung ist einfach, wenn Sie die oben genannten Regeln befolgen, dann ist friend harmlos. friend Die Überladungsdefinitionen des Boilyplates ermöglichen es, sie in die class { Zahnspange einzusetzen.

Beachten Sie, dass einige Betreiber nicht frei Funktionen können sein: =, ->, [] und (), weil der Standard sagt hierzu im Abschnitt 13.5. Ich denke, das ist alles ... Ich dachte, unary & und * waren auch, aber ich war anscheinend falsch. Sie sollten immer als Mitglieder jedoch überladen werden, und nur nach sorgfältiger Überlegung!

+0

Warum können unäre Operatoren keine Freunde sein? – Vijay

+2

Weil sie nicht nötig sind. Friend-Operatoren dürfen Ihnen ermöglichen, einen Klassentyp rechts von einem binären Operator anzugeben. Da unäre Operatoren keine rechte Seite haben, brauchen Sie sie nicht, um Freunde zu sein. – Stewart

+0

@cpp: Sorry, ich habe mich an den Standard nicht erinnert. Vergiss es. – Potatoswatter

3

Der Unterschied besteht darin, dass die friended-Funktion tatsächlich im globalen Gültigkeitsbereich liegt. Sie müssen also keine Instanz der Klasse sein, um darauf zugreifen zu können.

1

Eine Elementfunktion erfordert, dass der linke Operator von diesem Typ sein muss. Eine Friend-Funktion kann implizites Casting für den linken Operator ermöglichen.

So sagen wir zum Beispiel, dass wir eine BigInt-Klasse erstellen. Und wir erstellen einen Mitgliedsfunktionsoperator, um den rechten Operator von BigInt zu übernehmen.

Jetzt können wir auch sagen, dass BigInt einen Konstruktor hat, der ein reguläres int braucht. Dieser Konstruktor ist NICHT explizit (explizites Schlüsselwort) und benötigt einen Parameter. Das heißt, C++ kann implizit von int in BigInt konvertieren.

Wenn wir diese Dinge haben wir können dies tun:

BigInt foo (5); BigInt Bar; bar = foo + 5;

Aber wir können dies nicht:

BigInt foo (5) BigInt bar; bar = 5 + foo;

Wenn wir jedoch eine Friend-Funktion anstelle einer Member-Funktion verwenden, funktionieren beide.

0

Memberfunktionen können auf rvalues ​​aufgerufen werden, während freie Funktionen, die Verweise auf nicht-const akzeptieren, nicht mit rvalues ​​aufgerufen werden können. Beispiel: ++function_returning_iterator_by_value() kompiliert nur, wenn Sie operator++ als Mitglied implementieren.

1

Eine Elementfunktion erfordert, dass der Operator der linken Seite von diesem Typ sein muss. Eine Friend-Funktion kann implizites Casting für den linken Operator ermöglichen.

Verwandte Themen