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

Resuelto Bingo asked hace 12 años • 5 respuestas

Entiendo la sobrecarga de la mayoría de los 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 sabe la función del operador (por ejemplo operator->(...), a qué miembro se hace referencia)? ¿Puede saberlo? ¿Necesita siquiera saberlo?

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

Bingo avatar Jan 08 '12 20:01 Bingo
Aceptado

->

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

Si el valor de retorno es otro objeto de tipo de clase, no un puntero, entonces la búsqueda de miembros posterior también la maneja una operator->función. Esto se denomina "comportamiento de profundización". El lenguaje encadena las operator->llamadas 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 sólo es complicado porque 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 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 simplemente un operador binario normal como +, -y /. Ver también: ¿Son malas las sobrecargas de operador libre->*?

.*y.

Estos no se pueden sobrecargar. Ya existe un significado incorporado cuando el lado izquierdo es del tipo de clase. Quizás tendría un poco de 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.

La 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.

Potatoswatter avatar Jan 09 '2012 00:01 Potatoswatter

Operador -> es especial.

"Tiene restricciones adicionales y atípicas: 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 desreferencia de puntero. " Bruce Eckel: Pensando en CPP Vol-one: operador->

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

a->->func();

Simplemente puedes hacer:

a->func();

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

Totonga avatar Jan 08 '2012 13:01 Totonga

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* unario (es decir, la primera parte de lo que ->hace).

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

La semántica de ->la sobrecarga es algo extraña porque C++ le permite devolver un puntero normal (que se utilizará para encontrar el objeto señalado) o devolver una instancia de otra clase si esta clase también proporciona un ->operador. Cuando en este segundo caso se continúa la búsqueda del objeto desreferenciado a partir de esta nueva instancia.

6502 avatar Jan 08 '2012 13:01 6502

El ->operador no sabe a qué miembro se apunta, simplemente 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.

John Chadwick avatar Jan 08 '2012 13:01 John Chadwick