Sobrecarga de operadores: ¿función miembro versus función no miembro? [duplicar]

Resuelto badmaash asked hace 13 años • 2 respuestas

Leí que un operador sobrecargado declarado como función miembro es asimétrico porque solo puede tener un parámetro y el otro parámetro que se pasa automáticamente es el thispuntero. Por tanto, no existe ningún estándar para compararlos. Por otro lado, el operador sobrecargado declarado como a friendes simétrico porque pasamos dos argumentos del mismo tipo y, por tanto, se pueden comparar.

Mi pregunta es que cuando todavía puedo comparar el valor l de un puntero con una referencia, ¿por qué se prefieren los amigos? (Usar una versión asimétrica da los mismos resultados que simétrica) ¿Por qué los algoritmos STL usan solo versiones simétricas?

badmaash avatar Jan 07 '11 10:01 badmaash
Aceptado

Si define la función sobrecargada de su operador como función miembro, entonces el compilador traduce expresiones como s1 + s2a s1.operator+(s2). Eso significa que la función miembro sobrecargada del operador se invoca en el primer operando. ¡Así es como funcionan las funciones miembro!

¿Pero qué pasa si el primer operando no es una clase? Hay un problema importante si queremos sobrecargar un operador donde el primer operando no es un tipo de clase, más bien digamos double. Entonces no puedes escribir así 10.0 + s2. Sin embargo, puede escribir funciones miembro sobrecargadas de operador para expresiones como s1 + 10.0.

Para resolver este problema de orden , definimos la función sobrecargada del operador como friendSI necesita acceder privatea los miembros. Hágalo friendSÓLO cuando necesite acceder a miembros privados. De lo contrario, simplemente conviértalo en una función no miembro y no amigo para mejorar la encapsulación.

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
}

Lea estos:
Un pequeño problema al ordenar operandos
Cómo las funciones que no son miembros mejoran la encapsulación

Sarfaraz Nawaz avatar Jan 07 '2011 04:01 Sarfaraz Nawaz

No es necesariamente una distinción entre friendsobrecargas de operadores y sobrecargas de operadores de funciones miembro, como lo es entre sobrecargas de operadores globales y sobrecargas de operadores de funciones miembro.

Una razón para preferir una sobrecarga de operadores globales es si desea permitir expresiones en las que el tipo de clase aparece en el lado derecho de un operador binario. Por ejemplo:

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

Esto sólo funciona si hay una sobrecarga global del operador para

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

Tenga en cuenta que la sobrecarga del operador global no tiene por qué ser necesariamente una friendfunción. Esto sólo es necesario si necesita acceso a miembros privados de Foo, pero no siempre es así.

De todos modos, si Foosolo tuviera una sobrecarga del operador de función miembro, como:

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

...entonces sólo podríamos tener expresiones en las que Fooaparezca una instancia a la izquierda del operador más.

Charles Salvia avatar Jan 07 '2011 04:01 Charles Salvia