2008-10-06 12 views
14

En la Guía de estilo de Google C++, hay una sección sobre Operator Overloading que tiene una curiosa afirmación:"No puede reenviar clases declarar que sobrecarga el operador &"?

La sobrecarga también tiene sorprendentes ramificaciones. Por ejemplo, no puede reenviar clases declaradas que sobrecargan operator&.

Esto parece incorrecto, y no he podido encontrar ningún código que cause que GCC tenga un problema con él. ¿Alguien sabe a qué se refiere esa afirmación?

Respuesta

20

5.3.1 de la Norma tiene "La dirección de un objeto de tipo incompleto puede tomarse, pero si el tipo completo de ese objeto es un tipo de clase que declara operador &() como una función miembro, entonces el comportamiento no está definido (y no hay diagnóstico es requerido)."

Tampoco lo sé, pero como ha señalado otro afiche, es fácil ver cómo podría causar que un compilador genere código incorrecto.

0

Editado para dar cuenta de los comentarios:

Esta es una suposición, pero una de las principales razones para reenviar declarar es ser capaz de declarar punteros a esa clase. El compilador debe hacer suposiciones sobre la clase antes de tener la definición, por ejemplo, el tamaño de los punteros.

¿Es posible cambiar el tamaño de T * al sobrecargar al operador & por un T? (EDITAR: Comentarios - y creo que no) - pero

¿Qué supuesto se viola al sobrecargar al operador & - cómo cambia la clase?

Aquí hay una manera.

podría escribir:

class A; 

void f(A& x) { 
    A* xPointer = &x; 
} 

que tiene un nuevo significado si el operador &() está sobrecargado que si no es así, y el compilador puede pensar que puede generar código para ello, pero sería un error.

+0

El tamaño de un puntero será el mismo independientemente, ¿no? –

+0

Creo que los punteros son siempre del mismo tamaño (por lo que el compilador puede asumir el tamaño ...) excepto en el caso de los punteros a las funciones de los miembros, que en realidad no son "punteros" en el sentido tradicional. –

+0

Sí, creo que sí. Estoy tratando de partir de la premisa de que el punto de referencia para declarar un tipo es para que el compilador pueda comenzar a hacer suposiciones al respecto sin tener la declaración completa. ¿Qué supuesto se infringe al tener operador &. –

16

yo no había oído hablar de él tampoco, pero esto da resultados potencialmente confusas para el mismo código antes y después de la sobrecarga:

#include <iostream> 

class Foo; 

void bar (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

class Foo { 
public: 
    bool operator &() { return true; } 
}; 

void baz (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

int main() { 
    Foo foo; 

    bar(foo); 
    baz(foo); 

    return 0; 
} 

de salida:

0x7fff092c55df 
1 

Aunque hay otras razones por qué no harías eso de todos modos, la dirección de sobrecarga no funciona bien con stl o código genérico.

+0

Ahora que es interesante y tiene sentido. Tal vez no esté "prohibido" por el estándar, pero en cambio tiene resultados no confiables dependiendo de si la definición de la clase/estructura aún se proporciona. –

+1

+1 para el código de muestra que muestra el problema – Bill

6

Creo que la afirmación no es precisa. Al igual que las otras respuestas, estoy adivinando aquí. Primero, supongo que se están refiriendo a unary operator& and not binary operator&. Es decir:

int x = 5; 
int* p = &x; // unary & 
if (x & 1) // binary & 

Puede reenviar declare la clase que desee. Sin embargo, si la clase sobrecarga el operador unitario &, y llama al operador unario & en un puntero a uno de esos objetos, probablemente obtendrá un comportamiento incoherente (a veces simplemente obtendrá la dirección, y algunas veces llamará al método sobrecargado).) Esto podría convertirse fácilmente en algo casi imposible de depurar.


Me alegra que fizzer en realidad mirara el estándar y no solo adivinara.

+1

Como señaló fizzer, es un comportamiento indefinido. Nunca bueno –

0

La redacción no es clara, por supuesto, puede reenviar declarar la clase, pero la regla obviamente toma la posición que "no debería" cuando la clase sobrecarga operator&.

Reglas similares también están presentes en otras normas de codificación, por ejemplo JSF(pdf) regla 159 indica que operator& no debe estar sobrecargado.

1

Debido a la capacidad de sobrecargar al operador &, la biblioteca de impulso ofrece el handy template addressof() para encargarse de encontrar la dirección real de una clase. No es que sugiera que sobrecargue el operador &, pero si lo necesita, hay ayuda disponible.