Ésta es una de las muchas novedades de cómo se realiza la búsqueda de nombre.
Hay dos ámbitos de identificador en C++, uno para los tipos de clase y el ámbito de identificador general. El valor enum BAD reside en el alcance del identificador general, mientras que el tipo de clase BAR reside en el alcance del identificador de clase. Esa es la razón por la que se le permite tener tanto un valor enum como una clase con el mismo nombre: ambos nombres no colisionan.
Dentro de la clase BAD, las reglas de búsqueda del identificador encontrarán la clase MALA antes de encontrar la enumeración, y por lo tanto el error. Ahora, si califica completamente el identificador, la búsqueda del nombre primero verificará el alcance del identificador global y coincidirá con el valor enum. En el extremo opuesto, deberá agregar la palabra clave struct
o class
para declarar las variables de tipo BAD.
namespace foo {
enum bad { BAD; };
class BAD {
void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
};
}
int main() {
// foo::BAD b; // error, foo::BAD is an enum, not a type
class foo::BAD b; // correct
}
Ahora, recomendaría este uso. En general, no es una buena idea reutilizar un identificador como este. El código será más complejo, y probablemente engañoso para el lector casual (el mismo identificador no calificado se refiere a diferentes cosas cuando se usa en diferentes contextos). Si los nombres deben ser BAD
, considere usar un espacio de nombres o clase adjuntos para la clase o la enumeración (prefiera la enumeración allí).
Oh por favor ... ¿no puedes poner el enum en una 'estructura' propia para evitar el choque, por lo menos? –
Para mejorar la legibilidad, recomiendo elegir diferentes nombres para 'enum' y' class'. Recuerde, un objetivo mejor es producir software fácil de mantener en lugar de invocar sutilezas en el compilador o el lenguaje. –