¿Por qué no puede sobrecargar el '.' operador en C ++?

79

Sería muy útil poder sobrecargar el. operador en C ++ y devuelve una referencia a un objeto.

Puedes sobrecargar operator->y operator*pero nooperator.

¿Existe una razón técnica para esto?

Ferruccio
fuente
4
¿Puede dar un ejemplo de cuándo desea anular el '.' ¿operador?
Toon Krijthe
4
Generalmente, el caso de uso es "referencias inteligentes". Una especie de proxy.
ddaa
2
@Gamecat: Lea esta propuesta para agregar la capacidad de sobrecarga operator.y operator.*tiene algunos ejemplos.
Mankarse
1
@ToonKrijthe Los espacios alrededor .están permitidos, por lo que quizás algún truco de despacho dinámico inteligente pero atroz que permita expresar el producto punto como matrix1 . matrix2.
mwcz

Respuestas:

62

Vea esta cita de Bjarne Stroustrup :

Operador. (punto), en principio, podría sobrecargarse utilizando la misma técnica que se utiliza para ->. Sin embargo, hacerlo puede generar dudas sobre si una operación está destinada a la sobrecarga del objeto. o un objeto al que hace referencia. Por ejemplo:

class Y {
public:
    void f();
    // ...
};

class X {    // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};

void g(X& x)
{
    x.f();    // X::f or Y::f or error?
}

Este problema puede resolverse de varias formas. En el momento de la estandarización, no era obvio cuál sería la mejor manera. Para obtener más detalles, consulte El diseño y la evolución de C ++ .

Anton Gogolev
fuente
Cita completa de TDaEoC ++ en mi respuesta.
ddaa
15
Estoy tentado a rechazar esto por plagio / cambio de color. Al citar, cite literalmente, no modifique. Y usa los formatos de cotización.
Sebastian Mach
2
El ejemplo es solo una ambigüedad de resolución de sobrecarga, lo que indica la necesidad de una programación más cuidadosa (consulte: stackoverflow.com/questions/13554606/… ) Esta situación no debería servir como una razón para no sobrecargaroperator .
slashmais
@slashmais No. La justificación de operator.es un paralelo explícito con operator->. ¿Y cómo se puede sobrecargar la resolución?
curioso
Solo para señalar que más tarde, Bjarne Stroustrup estuvo a favor del operador dot e incluso impulsó una propuesta para eso, que aparentemente no fue (todavía) aceptada: http://www.open-std.org/jtc1/sc22/wg21/ docs / papers / 2015 / n4477.pdf - como ya lo agregó @emlai como comentario a la pregunta
Amir Kirsh
52

Stroustrup dijo que C ++ debería ser un lenguaje extensible, pero no mutable.

Se consideró que el operador de punto (acceso a atributos) estaba demasiado cerca del núcleo del lenguaje para permitir la sobrecarga.

Consulte El diseño y evolución de C ++ , página 242, sección 11.5.2 Referencias inteligentes .

Cuando decidí permitir la sobrecarga del operador ->, naturalmente consideré si el operador .podría estar igualmente sobrecargado.

En ese momento, consideré los siguientes argumentos concluyentes: Si objes un objeto de clase, entonces obj.mtiene un significado para cada miembro mde la clase de ese objeto. Tratamos de no hacer que el lenguaje sea mutable redefiniendo las operaciones integradas (aunque esa regla se viola por =una necesidad imperiosa y por unario &).

Si permitimos la sobrecarga de .una clase X, no podríamos acceder a los miembros de Xpor los medios normales; tendríamos que usar un puntero y ->, pero ->y &también podría haber sido redefinido. Quería un lenguaje extensible, no mutable.

Estos argumentos son contundentes, pero no concluyentes. En particular, en 1990 Jim Adcock propuso permitir la sobrecarga del operador . exactamente como lo ->es el operador .

El "yo" en esta cita es Bjarne Stroustrup. No puedes tener más autoridad que eso.

Si realmente quiere entender C ++ (como en "por qué es así"), debería leer este libro.

ddaa
fuente
28

Stroustrup tiene una respuesta para esta pregunta :

Operador. (punto), en principio, podría sobrecargarse utilizando la misma técnica que se utiliza para ->. Sin embargo, hacerlo puede generar dudas sobre si una operación está destinada a la sobrecarga del objeto. o un objeto al que hace referencia. Por ejemplo:

class Y {
public:
    void f();
    // ...
};
class X {   // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};
void g(X& x)
{
    x.f();  // X::f or Y::f or error?
}

Este problema puede resolverse de varias formas. En el momento de la estandarización, no era obvio cuál sería la mejor manera. Para obtener más detalles, consulte D&E .

mfazekas
fuente
1
Vea mi comentario sobre la respuesta de Anton
slashmais
1

Es muy fácil de entender, si pasa por el mecanismo interno de invocación de la función del operador, digamos que un complejo de clases puede tener dos miembros r para la parte real e i para la parte imaginaria. Diga Complex C1 (10,20), C2 (10,2) // asumimos que ya hay un constructor de dos argumentos dentro de la clase. Ahora, si escribe C1 + C2 como una declaración, el compilador intenta encontrar la versión sobrecargada del operador + en un número complejo. Ahora asumimos que sobrecargo + operador, por lo que C1 + C2 traducido internamente como c1.operador + (c2) Ahora supongamos que por el momento puede sobrecargar '.' operador. así que ahora piense en la siguiente llamada C1.disp () // muestra el contenido de un objeto complejo Ahora intente representarlo como una representación interna C1.operator. (------) , cosas completamente desordenadas creadas. Esa es la razón por la que no podemos sobrecargar '. operador

Sourav Ghosh
fuente
1
Algunas personas dicen traducidos interna no debe llamar a una sobrecargaoperator.
curiousguy
Vea una propuesta de C ++ sobre cómo esto puede ser útil y no tan complicado: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf
Amir Kirsh