En primer lugar, debe tenerse en cuenta que esto no tiene nada que ver con el operador que se está implementando como amigo específicamente. Se trata realmente de implementar la función de copia como función miembro o como función no miembro (independiente). Que esa función independiente sea o no amiga es completamente irrelevante: podría ser, tal vez no lo sea, dependiendo de lo que quiera acceder dentro de la clase.
Ahora, la respuesta a esta pregunta se encuentra en D & E book (The Design and Evolution of C++). La razón de esto es que el compilador siempre declara/define un operador de asignación de copia miembro para la clase (si no declara su propio operador de copia-asignación de miembros).
Si el idioma también permitió declarar operador de copia-asignación como un independiente (no miembro) función, que podría terminar con la siguiente
// Class definition
class SomeClass {
// No copy-assignment operator declared here
// so the compiler declares its own implicitly
...
};
SomeClass a, b;
void foo() {
a = b;
// The code here will use the compiler-declared copy-assignment for `SomeClass`
// because it doesn't know anything about any other copy-assignment operators
}
// Your standalone assignment operator
SomeClass& operator =(SomeClass& lhs, const SomeClass& rhs);
void bar() {
a = b;
// The code here will use your standalone copy-assigment for `SomeClass`
// and not the compiler-declared one
}
Como se ve en el ejemplo anterior, la semántica de la copia -la asignación cambiaría en el medio de la unidad de traducción: antes de la declaración de su operador independiente, se utiliza la versión del compilador. Después de la declaración, se usa su versión. El comportamiento del programa cambiará dependiendo de dónde coloque la declaración de su operador de copiado independiente.
Esto se consideró inaceptablemente peligroso (y lo es), por lo que C++ no permite que el operador de copia-asignación se declare como una función independiente.
Es cierto que en el ejemplo particular, que pasa a utilizar una función amigo específicamente, el operador se declara muy temprano, dentro de la definición de clase (ya que así es como se declaran amigos). Entonces, en su caso, el compilador sabrá de inmediato la existencia de su operador. Sin embargo, desde el punto de vista del lenguaje C++, el problema general no está relacionado con las funciones de amigo de ninguna manera. Desde el punto de vista del lenguaje C++, se trata de funciones miembro frente a funciones que no son miembros, y la sobrecarga de la asignación de copias por parte de no miembros está completamente prohibida por los motivos descritos anteriormente.
+1: Estoy celoso de la claridad que ha proporcionado detrás del razonamiento real. – Chubsdad
Lo siento, pero eso simplemente es incorrecto y no tiene ningún sentido. ¿Por qué el operador del compilador tiene prioridad? Para aquellos operadores que * pueden * declararse como funciones independientes, declarar la versión de miembro y la versión independiente conduce a * ambigüedad *, no a la función de miembro "tomando precedencia". ¿Cuál es la lógica detrás de la declaración en esta respuesta, entonces? – AnT
@AndreyT y @Billy Oneal: Ambos tienen razón, en diferentes contextos. Si la asignación se realizó dentro de un método de clase, debido a las reglas de búsqueda, la función miembro (en este caso generada por el compilador) tendría prioridad y ocultaría el ámbito de espacio de nombres 'operator ='. Si la asignación ocurre fuera del alcance de la clase, entonces habría ambigüedad y el compilador fallaría. Si bien esto no se puede probar con 'operator =', es bastante simple generar una prueba con 'operator + =' (o cualquier otro operador que se pueda implementar como miembro y como función libre) –