2010-05-05 17 views
9

¿Cuál es la diferencia entre la sobrecarga del operador utilizando la palabra clave friend y como una función miembro dentro de una clase?sobrecarga del operador (función de amigo y miembro)

Además, ¿cuál es la diferencia en el caso de una sobrecarga de un operador unario (es decir, como un amigo frente a una función miembro)?

Respuesta

12

Jacob tiene razón ... una función declarada dentro de una clase tiene acceso a esa clase, pero no está dentro de la clase, y todos los demás tienen acceso a ella.

Para una sobrecarga de operador que no es un miembro de la clase (también llamada función libre, puede ser un amigo, o tal vez no), los argumentos son los mismos que los operandos. Para uno que es miembro de una clase, el primer operando es el "argumento implícito" que se convierte en this.

El argumento implícito es diferente del primer argumento a una función gratuita de varias maneras:

  • Su tipo es la referencia a la clase, mientras que la función libre puede declarar cualquier tipo para su primer argumento.
  • No participa en la conversión de tipo implícita. (No será una inicialización temporal de un constructor de conversión.)
  • Participa en la resolución de anulación virtual. (A sobrecarga virtual será elegido por el tipo dinámico del primer operando, que no es posible con funciones libres sin código extra.)

La situación es la misma para unario, binario, o n-ary (en el caso de operator()).

miembros privilegio de mutación: operadores que cambian el primer operando (por ejemplo +=, =, prefijo ++) debe ser implementado como funciones miembro, y debe aplicar exclusivamente las tripas de todos sobrecargas. Postfix ++ es un ciudadano de segunda clase; está implementado como Obj ret = *this; ++ this; return ret;. Tenga en cuenta que esto a veces se extiende a copy-constructors, que puede contener *this = initializer.

Regla de libertad para viajeros: Solo los operadores conmutativos (p. Ej. /) deben ser funciones gratuitas; todos los demás operadores (por ejemplo, algo unario) deberían ser miembros. Los operadores conmutativos hacen inherentemente una copia del objeto; se implementan como Obj ret = lhs; ret @= rhs; return ret; donde @ es el operador conmutativo y lhs y rhs son argumentos del lado izquierdo y del lado derecho, respectivamente.

Golden rule of C++ friendship: Evita la amistad. friend contamina la semántica de un diseño. Corolario de sobrecarga: La sobrecarga es simple si sigue las reglas anteriores, entonces friend es inofensivo. friend ing. Las definiciones de sobrecarga de las calcomanías les permiten ubicarse dentro de las llaves class {.

Tenga en cuenta que algunos operadores no pueden ser funciones gratuitas: =, ->, [] y (), debido a que la norma dice específicamente por lo que en la sección 13.5. Creo que eso es todo ... Pensé que unario & y * también, pero aparentemente estaba equivocado. Ellos deberían siempre estar sobrecargados como miembros, sin embargo, ¡y solo después de una cuidadosa reflexión!

+0

¿por qué los operadores unarios no pueden ser amigos? – Vijay

+2

Porque no es necesario que lo sean. Los operadores amigos pueden permitirle poner un tipo de clase a la derecha de un operador binario. Como los operadores unarios no tienen el lado derecho, no los necesitas para que sean amigos. – Stewart

+0

@cpp: Lo siento, recordé mal el estándar. No importa. – Potatoswatter

3

La diferencia es que la función de comunicación está en el alcance global, por lo que no necesita ser una instancia de la clase para tener acceso a ella.

1

Una función miembro requiere que el operador de la mano izquierda deba ser de ese tipo. Una función de amigo puede permitir la conversión implícita en el operador de la mano izquierda.

Así que, por ejemplo, digamos que creamos una clase BigInt. Y creamos un operador de función miembro + para tomar un operador de la mano derecha de BigInt.

Ahora también digamos que BigInt tiene un constructor que toma una int regular. Este constructor NO es explícito (palabra clave explícita) y requiere un parámetro. Eso significa que C++ puede convertir literalmente de int a BigInt.

Cuando tenemos estas cosas que podemos hacer esto:

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

pero no podemos hacer esto:

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

Sin embargo, si usamos una función de amigo en lugar de una función de miembro, ambas funcionarán.

0

Las funciones de miembro se pueden invocar en rvalues, mientras que las funciones libres que aceptan referencias a no-const no se pueden invocar con valores r. Por ejemplo, ++function_returning_iterator_by_value() solo compila si implementa operator++ como miembro.

1

Una función miembro requiere que el operador de la mano izquierda deba ser de ese tipo. Una función de amigo puede permitir la conversión implícita en el operador de la mano izquierda.

Cuestiones relacionadas