Sobrecargar operadores de acceso de miembros ->,.* (C++)


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

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

¿Cómo funciona el operador (por ejemplo, operator->(...)) saber a qué miembro se hace referencia? ¿Puede saberlo? ¿Necesita saberlo?

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

Author: sbi, 2012-01-08

5 answers

->

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

Si el valor devuelto es otro objeto de tipo clase, no un puntero, entonces la búsqueda de miembros posterior también es manejada por una función operator->. Esto se llama el "comportamiento de drill-down."El lenguaje encadena las llamadas operator-> hasta que la última 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 en que no hay nada especial en él. La versión no sobrecargada requiere un objeto de puntero a tipo clase en el lado izquierdo y un objeto de puntero a tipo miembro en el lado derecho. Pero cuando lo sobrecargas, puedes tomar cualquier argumento 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: ¿El operador libre - >* sobrecarga el mal?

.* y .

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

Sobrecarga ->, ->*, ., and .* can only fill in cases where an expresión sería indefinida, nunca puede cambiar el significado de una expresión que sería válida sin sobrecarga.

 114
Author: Potatoswatter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:39

El 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: Pensando CPP Vol-one: operador->

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

a->->func();

Usted puede simplemente do:

a->func();

Que hace que operator -> sea diferente de las sobrecargas de otros operadores.

 22
Author: Totonga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-26 04:43:57

No se puede sobrecargar el acceso de los miembros . (es decir, la segunda parte de lo que hace ->). Sin embargo, puede sobrecargar el operador unario desreferenciación * (es decir, la primera parte de lo que 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 -> la sobrecarga es algo extraño porque C++ le permite devolver un puntero regular (que se utilizará 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.

 20
Author: 6502,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-08 23:28:09

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 const y no const.

 8
Author: John Chadwick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-08 13:20:53

Cuando se sobrecarga el operador->() (no se pasan argumentos aquí), lo que el compilador realmente hace es llamar a -> recursivamente hasta que devuelve un puntero real a un tipo. A continuación, utiliza el miembro/método correcto.

Esto es útil, por ejemplo, para crear una clase de puntero inteligente que encapsula el puntero real. El operador sobrecargado-> es llamado, hace lo que hace (por ejemplo, bloqueo para la seguridad del hilo), devuelve el puntero interno y luego el compilador llama a - > para este interno puntero.

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

 5
Author: Asaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-08 13:37:27