Sobrecarga de operadores de acceso a miembros ->, .*

6 minutos de lectura

Sobrecarga de operadores de acceso a miembros
Bingo

Entiendo la mayoría de la sobrecarga de operadores, con la excepción de los operadores de acceso a miembros. ->, .*, ->* etc

En particular, ¿qué se pasa a estas funciones de operador y qué se debe devolver?

¿Cómo funciona el operador (p. ej. operator->(...) ) sabe a qué miembro se hace referencia? ¿Puede saberlo? ¿Incluso necesita saberlo?

Finalmente, ¿hay alguna consideración constante que deba tenerse en cuenta? Por ejemplo, al sobrecargar algo como operator[], generalmente necesitará una versión const y no const. ¿Los operadores de acceso de miembros requieren versiones constantes y no constantes?

  • Creo que las preguntas frecuentes de C++ anteriores tocan todas las preguntas que se preguntan en la pregunta anterior.

    – Alok Guardar

    8 de enero de 2012 a las 13:19

  • const y no-const versiones de operator-> no son requeridopero proporcionar ambos puede ser útil.

    – Fred Foo

    8 de enero de 2012 a las 13:26

  • Ver también: yosefk.com/c++fqa/operator.html

    – György Andrasek

    8 de enero de 2012 a las 13:42

  • @Als: las preguntas frecuentes no explican cómo sobrecargar ->* y .*. De hecho, ¡ni siquiera los menciona! Siento que son demasiado raros para estar en las preguntas frecuentes, pero con gusto vincularía esta pregunta desde las preguntas frecuentes. ¡Por favor, no cierre esto como un engaño de las preguntas frecuentes!

    – sbi

    19 de enero de 2012 a las 11:56


  • @sbi, simplemente no pude encontrar un enlace a esta pregunta en sus (increíbles) preguntas frecuentes y terminé haciendo una pregunta duplicada. ¿Podrías hacerlo más obvio? (disculpas si ya es obvio).

    – Pi

    29 de diciembre de 2014 a las 14:18

Sobrecarga de operadores de acceso a miembros
matapatatas

->

Este es el único realmente complicado. Debe ser una función miembro no estática y no requiere argumentos. El valor devuelto se utiliza para realizar la búsqueda de miembros.

Si el valor devuelto es otro objeto de tipo de clase, no un puntero, la búsqueda de miembros subsiguiente también es manejada por un operator-> función. Esto se denomina “comportamiento de profundización”. El lenguaje encadena la 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 solo es complicado porque no tiene nada de especial. los no sobrecargado requiere un objeto de tipo puntero a clase en el lado izquierdo y un objeto de tipo puntero a miembro en el lado derecho. Pero cuando lo sobrecargas, puedes tomar los argumentos que quieras y devolver lo que quieras. 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: ¿Son malas las sobrecargas de operador->* libres?

.* y .

Estos no se pueden sobrecargar. Ya hay un significado incorporado cuando el lado izquierdo es del tipo de clase. Tal vez tendría un poco de sentido poder definirlos para un puntero en el lado izquierdo, pero el comité de diseño de idiomas decidió que sería más confuso que útil.

Sobrecarga ->, ->*, .y .* solo puede completar los casos en los que una expresión no estaría definida, nunca puede cambiar el significado de una expresión que sería válida sin sobrecarga.

  • Tu última afirmación no es del todo cierta. Por ejemplo, puede sobrecargar el new operador, aunque es válido incluso cuando no está sobrecargado.

    – Mate

    17 de febrero de 2013 a las 4:49

  • @Matt bueno, new siempre está sobrecargado, o las reglas de sobrecarga realmente no se aplican a él (13.5/5: Las funciones de asignación y desasignación, operador nuevo, operador nuevo[]eliminación de operador y eliminación de operador[], se describen completamente en 3.7.4. Los atributos y restricciones que se encuentran en el resto de esta subcláusula no se aplican a ellos a menos que se indique explícitamente en 3.7.4.) Pero la sobrecarga unaria & o binario &&, ||o ,o agregando sobrecargas de operator=, o sobrecargar casi cualquier cosa para un tipo de enumeración sin ámbito, puede cambiar el significado de una expresión. Aclarado el comunicado, gracias!

    – Patatas

    18 de febrero de 2013 a las 1:05

1646965270 595 Sobrecarga de operadores de acceso a miembros
Totonga

Operador -> es especial.

“Tiene restricciones atípicas adicionales: debe devolver un objeto (o referencia a un objeto) que también tiene un operador de desreferencia de puntero, o debe devolver un puntero que se puede usar para seleccionar a qué apunta la flecha del operador de desreferencia de puntero. ”
Bruce Eckel: Thinking CPP Vol-one : operador->

La funcionalidad adicional se proporciona para mayor comodidad, por lo que no tiene que llamar

a->->func();

Simplemente puede hacer:

a->func();

Eso hace que operator -> sea diferente de las otras sobrecargas de operadores.

  • Esta respuesta merece más crédito, puede descargar el libro de Eckel desde ese enlace y la información está en el capítulo 12 del volumen uno.

    – Pi

    29 de diciembre de 2014 a las 14:36

1646965270 868 Sobrecarga de operadores de acceso a miembros
6502

No puede sobrecargar el acceso de miembros . (es decir, la segunda parte de lo que -> lo hace). Sin embargo, puede sobrecargar el unario desreferenciar operador * (es decir, la primera parte de lo que -> lo hace).

El C++ -> operador es básicamente la unión de dos pasos y esto es claro si piensas que x->y es equivalente a (*x).y. C++ le permite personalizar qué hacer con el (*x) parte cuando x es una instancia de tu clase.

La semántica para -> la sobrecarga es algo extraña porque C++ le permite devolver un puntero normal (que se usará para encontrar el objeto apuntado) 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.

  • ¡Gran explicación! Supongo que eso significa lo mismo para ->*ya que es equivalente a la forma de (*x).* ?

    – Bingo

    8 de enero de 2012 a las 23:34

los -> El operador no sabe a qué miembro se está apuntando, solo proporciona un objeto para realizar el acceso real al miembro.

Además, no veo ninguna razón por la que no pueda proporcionar versiones constantes y no constantes.

Cuando sobrecarga operator->() (aquí no se pasan 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 encapsule el puntero real. Se llama al operador sobrecargado->, hace lo que hace (por ejemplo, bloqueo para seguridad de subprocesos), devuelve el puntero interno y luego el compilador llama a -> para este puntero interno.

En cuanto a la constancia, se ha respondido en los comentarios y otras respuestas (puede y debe proporcionar ambas).

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad