Eu entendo mais sobrecarga de operadores, com excepção dos operadores de acesso membro ->
, .*
, ->*
etc.
Em particular, o que é passado para essas funções do operador e o que deve ser retornado?
Como o operador funciona (por exemplo operator->(...)
) sabe a que membro está sendo referido? Ele pode saber? Precisa mesmo saber?
Finalmente, existem considerações constantes que precisam ser levadas em consideração? Por exemplo, ao sobrecarregar algo como operator[]
, geralmente você precisará de uma versão const e não-const. Os operadores de acesso a membros exigem versões const e não-const?
c++
operator-overloading
c++-faq
Bingo
fonte
fonte
const
e nãoconst
versõesoperator->
não são necessárias , mas fornecer ambos pode ser útil.->*
e.*
. Na verdade, nem sequer os menciona! Eu sinto que eles são raros em estar em uma FAQ, mas gostaria de vincular esta pergunta a partir da FAQ. Por favor, não feche isso como uma fraude do FAQ!Respostas:
->
Este é o único realmente complicado. Deve ser uma função de membro não estática e não requer argumentos. O valor de retorno é usado para executar a consulta do membro.
Se o valor de retorno for outro objeto do tipo de classe, não um ponteiro, a pesquisa subsequente do membro também será tratada por uma
operator->
função. Isso é chamado de "comportamento de detalhamento". O idioma une asoperator->
chamadas até a última retornar um ponteiro.->*
Este é apenas complicado, pois não há nada de especial nisso. A versão não sobrecarregada requer um objeto de ponteiro para o tipo de classe no lado esquerdo e um objeto de ponteiro para o tipo de membro à direita. Mas quando você o sobrecarrega, pode pegar os argumentos que quiser e retornar o que quiser. Nem precisa ser um membro não estático.
Em outras palavras, este é apenas um operador binário normal como
+
,-
, e/
. Veja também: O operador livre -> * sobrecarrega o mal?.*
e.
Estes não podem ser sobrecarregados. Já existe um significado interno quando o lado esquerdo é do tipo de classe. Talvez faça algum sentido poder defini-los para um ponteiro no lado esquerdo, mas o comitê de design de idiomas decidiu que seria mais confuso do que útil.
Sobrecarga
->
,->*
,.
, e.*
só pode preencher nos casos em que uma expressão seria indefinida, ele nunca pode mudar o significado de uma expressão que seria válido sem sobrecarga.fonte
new
operador, mesmo que seja válido mesmo quando não estiver sobrecarregado.new
está sempre sobrecarregado ou as regras de sobrecarga não se aplicam a ele (13.5 / 5: as funções de alocação e desalocação, operador novo, operador novo [], operador novo [], operador excluir e operador excluir []) são descritas completamente em 3.7 .4. os atributos e restrições encontradas no resto deste subitem não se aplicam a eles a menos que explicitamente indicado em 3.7.4.) Mas a sobrecarga unário&
ou binário&&
,||
ou,
, ou a adição de sobrecargas deoperator=
, ou sobrecarregar qualquer coisa por um sem escopo tipo de enumeração, pode alterar o significado de uma expressão. Esclareceu a declaração, obrigado!Operador -> é especial.
"Possui restrições atípicas adicionais: ele deve retornar um objeto (ou referência a um objeto) que também possui um operador de desreferência de ponteiro, ou deve retornar um ponteiro que possa ser usado para selecionar o que a seta do operador de desreferência de ponteiro está apontando. " Bruce Eckel: Pensando em CPP Vol-one: operador->
A funcionalidade extra é fornecida por conveniência, para que você não precise ligar
Você pode simplesmente fazer:
Isso torna o operador -> diferente das outras sobrecargas do operador.
fonte
Você não pode sobrecarregar o acesso dos membros
.
(ou seja, a segunda parte do que->
faz). No entanto, pode sobrecarregar o unário dereferencing operador*
(ou seja, a primeira parte do que->
faz).O
->
operador C ++ é basicamente a união de duas etapas e isso fica claro se você pensa quex->y
é equivalente a(*x).y
. O C ++ permite que você personalize o que fazer com a(*x)
parte quandox
é uma instância da sua classe.A semântica para
->
sobrecarga é um tanto estranha, pois o C ++ permite retornar um ponteiro regular (que será usado para encontrar o objeto apontado) ou retornar uma instância de outra classe se essa classe também fornecer um->
operador. Quando, neste segundo caso, a procura pelo objeto desreferenciado continua a partir desta nova instância.fonte
->*
, pois é equivalente à forma de(*x).*
?O
->
operador não sabe para qual membro está sendo apontado, apenas fornece um objeto para executar o acesso real do membro.Além disso, não vejo razão para que você não possa fornecer versões const e non-const.
fonte
Quando você sobrecarrega o operador -> () (nenhum argumento é passado aqui), o que o compilador realmente faz é chamar -> recursivamente até retornar um ponteiro real para um tipo. Em seguida, ele usa o membro / método correto.
Isso é útil, por exemplo, para criar uma classe de ponteiro inteligente que encapsule o ponteiro real. O operador sobrecarregado-> é chamado, faz o que faz (por exemplo, travar para segurança da thread), retorna o ponteiro interno e, em seguida, o compilador chama -> para esse ponteiro interno.
Quanto à constância, ela foi respondida nos comentários e em outras respostas (você pode e deve fornecer as duas).
fonte