sobrecargar - Sobrecarga de operadores de acceso a miembros->,.*(C++)
sobrecarga de operadores unarios en c++ (5)
->
Este es el único realmente complicado. Debe ser una función miembro no estática y no requiere argumentos. El valor de retorno se usa para realizar la búsqueda de miembro.
Si el valor de retorno es otro objeto del tipo de clase, no un puntero, la búsqueda de miembro subsiguiente también se maneja mediante una función operator->
. Esto se llama el "comportamiento de desglose". El lenguaje encadena el operator->
llama hasta que el último devuelve un puntero.
struct client
{ int a; };
struct proxy {
client *target;
client *operator->() const
{ return target; }
};
struct proxy2 {
proxy *target;
proxy &operator->() const
{ return * target; }
};
void f() {
client x = { 3 };
proxy y = { & x };
proxy2 z = { & y };
std::cout << x.a << y->a << z->a; // print "333"
}
->*
Este es solo complicado ya que no tiene nada de especial. La versión no sobrecargada requiere un objeto de puntero al tipo de clase en el lado izquierdo y un objeto de puntero al tipo de miembro a la derecha. Pero cuando lo sobrecarga, puede tomar cualquier argumento que desee y devolver lo que quiera. Ni siquiera tiene que ser un miembro no estático.
En otras palabras, este es solo un operador binario normal como +
, -
y /
. Ver también: ¿El operador libre -> * sobrecarga el mal?
.*
y .
Estos no pueden ser sobrecargados. Ya existe un significado incorporado cuando el lado izquierdo es del tipo de clase. Tal vez tendría poco sentido poder definirlos para un puntero en el lado izquierdo, pero el comité de diseño del lenguaje decidió que sería más confuso que útil.
Sobrecarga ->
, ->*
.
y .*
solo puede rellenar casos en los que una expresión sería indefinida, nunca puede cambiar el significado de una expresión que sería válida sin sobrecarga.
Entiendo que la mayoría de las sobrecargas del operador, con la excepción de los operadores de acceso a miembros ->
.*
, ->*
etc.
En particular, ¿qué se pasa a estas funciones del operador y qué se debe devolver?
¿Cómo funciona el operador (por ejemplo, operator->(...)
) saber a qué miembro se está haciendo referencia? ¿Puede saber? ¿Necesita siquiera saberlo?
Finalmente, ¿hay alguna consideración constante que deba tenerse en cuenta? Por ejemplo, cuando se sobrecarga algo como operator[]
, generalmente necesitará una versión const y otra const. ¿Los operadores de acceso de miembros requieren versiones const y non-const?
Cuando sobrecarga el operador -> () (aquí no se pasan los argumentos), lo que el compilador realmente hace es llamar -> recursivamente hasta que devuelve un puntero real a un tipo. Luego usa el miembro / método correcto.
Esto es útil, por ejemplo, para crear una clase de puntero inteligente que encapsula el puntero real. Se llama al operador sobrecargado->, hace lo que haga (por ejemplo, bloqueo para la seguridad del hilo), devuelve el puntero interno y luego el compilador llama a> - para este puntero interno.
En cuanto a la constness, se ha respondido en los comentarios y otras respuestas (puede y debe proporcionar ambos).
El operador ->
no sabe a qué miembro se lo está apuntando, solo proporciona un objeto para realizar el acceso de miembro real.
Además, no veo ninguna razón por la cual no puedas proporcionar versiones const y no const.
No puede sobrecargar el acceso de los miembros .
(es decir, la segunda parte de lo que ->
hace). Sin embargo, puede sobrecargar el operador de desreferenciación único *
(es decir, la primera parte de qué ->
hace).
El operador C ++ ->
es básicamente la unión de dos pasos y esto está claro si crees que x->y
es equivalente a (*x).y
. C ++ le permite personalizar qué hacer con la parte (*x)
cuando x
es una instancia de su clase.
La semántica para ->
sobrecargar es algo extraña porque C ++ le permite devolver un puntero regular (que se usará para encontrar el objeto puntiagudo) o devolver una instancia de otra clase si esta clase también proporciona un operador ->
. Cuando en este segundo caso la búsqueda del objeto desreferenciado continúa desde esta nueva instancia.
Operador -> es especial.
"Tiene restricciones atípicas adicionales: debe devolver un objeto (o referencia a un objeto) que también tenga un operador de desreferencia de puntero, o debe devolver un puntero que pueda usarse para seleccionar a qué apunta la flecha del operador de referencia de puntero. " Bruce Eckel: Pensando CPP Vol-one: operador->
La funcionalidad adicional se proporciona para su comodidad, por lo que no tiene que llamar
a->->func();
Simplemente puede hacer:
a->func();
Eso hace que el operador -> sea diferente de las otras sobrecargas del operador.