Eu li que um operador sobrecarregado declarado como função de membro é assimétrico porque pode ter apenas um parâmetro e o outro parâmetro passado automaticamente é o this
ponteiro. Portanto, não existe um padrão para compará-los. Por outro lado, o operador sobrecarregado declarado como a friend
é simétrico porque passamos dois argumentos do mesmo tipo e, portanto, eles podem ser comparados.
Minha pergunta é que, quando ainda posso comparar o lvalue de um ponteiro com uma referência, por que os amigos são preferidos? (usar uma versão assimétrica dá os mesmos resultados que simétrica) Por que os algoritmos STL usam apenas versões simétricas?
Respostas:
Se você definir sua função sobrecarregada de operador como função de membro, o compilador traduzirá expressões como
s1 + s2
ems1.operator+(s2)
. Isso significa que a função de membro sobrecarregada do operador é chamada no primeiro operando. É assim que funcionam as funções de membro!Mas e se o primeiro operando não for uma classe? Há um grande problema se quisermos sobrecarregar um operador onde o primeiro operando não é um tipo de classe, digamos
double
. Então você não pode escrever assim10.0 + s2
. No entanto, você pode escrever função de membro com sobrecarga de operador para expressões comos1 + 10.0
.Para resolver esse problema de ordenação , definimos a função sobrecarregada do operador como
friend
SE ela precisa acessar osprivate
membros. Faça-ofriend
SOMENTE quando precisar acessar membros privados. Caso contrário, simplesmente torne -a uma função não-membro não-amiga para melhorar o encapsulamento!Leia estes:
Um pequeno problema de ordenação de operandos
Como funções de não membros melhoram o encapsulamento
fonte
friend
apenas quando precisar acessar membros privados ... e quando você não tiver / estiver entediado de escrever acessadores, certo?a/b
.friend
é implementá-los em termos dos operadores de atribuição de operação (que quase certamente serão membros públicos). Por exemplo, você pode definirT T::operator+=(const T &rhs)
como membro e, em seguida, definir não membroT operator(T lhs, const T &rhs)
comoreturn lhs += rhs;
. A função não membro deve ser definida no mesmo namespace da classe.Não é necessariamente uma distinção entre
friend
sobrecargas de operador e sobrecargas de operador de função de membro, pois é entre sobrecargas de operador global e sobrecarga de operador de função de membro.Uma razão para preferir um mundial sobrecarga de operador é se você quiser permitir que expressões onde o tipo de classe aparece no direito lado de um operador binário. Por exemplo:
Isso só funciona se houver uma sobrecarga de operador global para
Observe que a sobrecarga do operador global não precisa necessariamente ser uma
friend
função. Isso só é necessário se precisar de acesso a membros privados deFoo
, mas nem sempre é o caso.Independentemente disso, se
Foo
tivesse apenas uma sobrecarga de operador de função de membro, como:... então, só poderíamos ter expressões em que uma
Foo
instância apareça à esquerda do operador mais.fonte