2010-02-12 15 views
10

Tengo una clase y un valor enum que tienen el mismo nombre. Dentro de la clase, quiero usar la enumeración que da un error. ¿Hay alguna manera de utilizar la enumeración sin cambiar el nombre o mover a un espacio de nombres diferente?use class y enum con el mismo nombre?

Ejemplo:

namespace foo { 
    enum bar { 
     BAD 
    }; 

    class BAD { 
     void worse() { 
      bar b = BAD; // error 
     } 
    }; 
}; 
+0

Oh por favor ... ¿no puedes poner el enum en una 'estructura' propia para evitar el choque, por lo menos? –

+0

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

Respuesta

9

É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í).

0

No, no hay manera de hacerlo. Debe usar un identificador válido. El identificador válido significa que debe poder identificar con él. :)

5
bar b = foo::BAD; 

o si se encuentra en el espacio de nombres global

bar b = ::BAD; 

pero ese nombre sobrecarga no es algo que recomiendo. C++ 0X permitirá

bar b = bar::BAD; 

que es una solución mejor si la dependencia de C++ 0X es aceptable.

Como prometió, la explicación

9,1/2

Si un nombre de clase se declara en un ámbito donde un objeto, función o empadronador del mismo nombre también es declarado, entonces ambas declaraciones están en el ámbito, la clase puede ser referido solamente usando un elaborado de tipo-especificador (3.4.4)

el elaborado de tipo-especificador es la forma

class BAD b; 

Esto es para la compatibilidad con C, donde los nombres de etiqueta están en un espacio de nombres diferentes y deben ser [i] typedef [/ i] ed si uno desea utilizarlos sin un-de tipo elaborado especificador. (Un ejemplo bien conocido con una función es la struct stat y la función stat en Unix).

que explican por qué la sobrecarga de un nombre para designar una clase y un empadronador es posible. La razón por la cual BAD designar la clase aquí es que el nombre de la clase se define también en el ámbito de la clase y en la definición de una función miembro del alcance buscado están en orden: - el alcance función miembro - el ámbito de la clase - la espacio de nombres que contiene la definición de clase

BAD se encuentra en el ámbito de la clase, por lo que el espacio de nombres foo no se busca.

+0

Alguien quería saber si lo probé. Lo hice con 3 compiladores diferentes, incluyendo como. Las reglas son arcanas, si recuerdo cuando tengo tiempo, daré una explicación más completa con referencias. – AProgrammer

+0

++, tiene razón acerca de esto –

0

Esto funciona en VS2008, pero da una advertencia:

bar b = bar::BAD; 

No es algo que puedo recomendar.

Debe poner la enumeración dentro de otro espacio de nombres dentro de foo y calificar bar y BAD con el nuevo espacio de nombres.

+0

Esa es sintaxis C++ 0X y es la solución preferida si está disponible. Mi solución es la sintaxis C++ 03 (pero use reglas arcanas). – AProgrammer

Cuestiones relacionadas