Se prefiere la versión no miembro (amigo o no) porque puede admitir conversiones implícitas tanto en el lado izquierdo como derecho del operador.
Dado un tipo que es convertir implícitamente a Objeto:
struct Widget
{
operator Object() const;
};
Sólo la versión no miembro puede ser llamado si una instancia de Widget
aparece en el lado izquierdo:
Widget w;
Object o;
o + w; // can call Object::operator+(Object &) since left-hand side is Object
w + o; // can only call operator+(Object &, Object &)
En respuesta a tu comentario:
Al definir la conversión op erator en Widget
, notificamos al compilador que las instancias de Widget
se pueden convertir automáticamente a instancias de Object
.
Widget w;
Object o = w; // conversion
En la expresión o + w
, el compilador llama Object::operator+(Object &)
con un argumento generada por la conversión a un w
Object
. El resultado es lo mismo que escribir o + w.operator Object()
.
Pero en la expresión w + o
, el compilador busca Widget::operator+
(que no existe) o un no miembro operator+(Widget, Object)
. Este último puede invocarse convirtiendo w
en Object
como se indica arriba.
Probablemente es mejor citar los bits relevantes desde la última pregunta, para que la gente no tenga que hacer clic en ella (y también en caso de que la pregunta desaparezca) – nneonneo