Suponha que tenhamos enum
o seguinte:
enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Eu quero criar uma instância disso enum
e inicializá-lo com um valor adequado, então eu faço:
Days day = Days.Saturday;
Agora eu quero verificar minha variável ou instância com um enum
valor existente , então eu faço:
if (day == Days.Saturday)
{
std::cout << "Ok its Saturday";
}
O que me dá um erro de compilação:
erro: expressão primária esperada antes de '.' símbolo
Então, para ficar claro, qual é a diferença entre dizer:
if (day == Days.Saturday) // Causes compilation error
e
if (day == Saturday)
?
A que esses dois realmente se referem, em que um está OK e um causa um erro de compilação?
Respostas:
Este código está errado:
Porque
Days
não é um escopo, nem um objeto. É um tipo. E os próprios tipos não têm membros. O que você escreveu é o equivalente astd::string.clear
.std::string
é um tipo, então você não pode usá.
-lo. Você usa.
em uma instância de uma classe.Infelizmente, as enums são mágicas e, portanto, a analogia pára por aí. Porque com uma classe, você pode fazer
std::string::clear
para obter um ponteiro para a função de membro, mas no C ++ 03,Days::Sunday
é inválido. (O que é triste). Isso ocorre porque o C ++ é (um pouco) retrocompatível com C e C não tinha namespaces, portanto, as enumerações precisavam estar no namespace global. Portanto, a sintaxe é simplesmente:Felizmente, Mike Seymour observa que isso foi abordado no C ++ 11. Mude
enum
paraenum class
e obtém seu próprio escopo; portanto,Days::Sunday
não é apenas válido, mas é a única maneira de acessarSunday
. Dias felizes!fonte
enum
paraenum class
e obtém seu próprio escopo; portanto,Days::Sunday
não é apenas válido, mas é a única maneira de acessarSunday
. Dias felizes!'.' token
edot operator
, exceto um símbolo e não um operador, e mostra o símbolo exato, e não um nome.enum
, não poderá usar nenhum escopo ou o escopo global (::Saturday
). Se você tem umenum class
(o que é uma coisa muito diferente), é necessário usá-loDays::Saturday
.Isso será suficiente para declarar sua variável enum e compará-la:
fonte
Days
não é um escopo, nem objeto. É um tipo. E os próprios tipos não têm membros.std::string.clear
também falha ao compilar pelo mesmo motivo.enum class
novo em 2011) têm escopo próprio e são acessados usando o operador de escopoDays::Saturday
,. O operador de acesso a membros (.
) é usado apenas para acessar membros da classe.Muito disso deve fornecer erros de compilação.
Agora,
Saturday
,Sunday
, etc. pode ser usado como de nível superior constantes descalços, eDays
pode ser usado como um tipo:E da mesma forma mais tarde, para testar:
Esses
enum
valores são como constantes nuas - sem escopo - com uma pequena ajuda extra do compilador: (a menos que você esteja usando classes enum C ++ 11 ), eles não são encapsulados como membros de objeto ou estrutura, por exemplo, e você não pode se referir a eles como membros deDays
.Você terá o que procura com o C ++ 11 , que apresenta
enum class
:Observe que esse C ++ é um pouco diferente de C de duas maneiras: uma é que C requer o uso da
enum
palavra - chave ao declarar uma variável:fonte
Você pode usar um truque para usar escopos como desejar, basta declarar enum da seguinte maneira:
fonte
Em vez de usar um monte de instruções if, as enums se prestam bem para alternar instruções
Eu uso algumas combinações de enum / switch no construtor de níveis que estou construindo para o meu jogo.
EDIT: Outra coisa, eu vejo que você quer sintaxe semelhante a;
Você pode fazer isso em C ++:
Aqui está um exemplo muito simples:
EnumAppState.h
Somefile.cpp
fonte
Se você ainda estiver usando o C ++ 03 e quiser usar enumerações, use enumerações dentro de um espaço para nome. Por exemplo:
Você pode usar a enumeração fora do namespace, como
fonte
Você está procurando enumerações fortemente tipadas , um recurso disponível no padrão C ++ 11 . Transforma enumerações em classes com valores de escopo.
Usando seu próprio exemplo de código, é:
O uso
::
como acessador de enumerações falhará se tiver como alvo um padrão C ++ anterior ao C ++ 11. Mas alguns compiladores antigos não o suportam, e alguns IDEs simplesmente substituem essa opção e configuram um padrão C ++ antigo.Se você estiver usando o GCC, ative o C + 11 com -std = c ++ 11 ou -std = gnu11 .
Seja feliz!
fonte
enum class Days { ...
.Isso não deve funcionar em C ++:
Dias não é um escopo ou objeto que contém membros que você pode acessar com o operador de ponto. Essa sintaxe é apenas um ismo de C # e não é legal em C ++.
A Microsoft mantém há muito tempo uma extensão C ++ que permite acessar os identificadores usando o operador de escopo:
Mas isso não é padrão antes do C ++ 11. No C ++ 03, os identificadores declarados em uma enumeração existem apenas no mesmo escopo que o próprio tipo de enumeração.
O C ++ 11 torna legal qualificar identificadores de enum com o nome de enum e também introduz classes de enum, que criam um novo escopo para os identificadores em vez de colocá-los no escopo circundante.
fonte
Infelizmente, os elementos do enum são 'globais'. Você os acessa fazendo
day = Saturday
. Isso significa que você não pode terenum A { a, b } ;
eenum B { b, a } ;
porque eles estão em conflito.fonte
enum class
no C ++ 11, é isso. Antes disso, você precisa fazer aulas fictícias.Enquanto o C ++ (excluindo o C ++ 11) possui enumerações, os valores neles são "vazados" no espaço para nome global.
Se você não deseja que eles vazem (e NÃO PRECISA usar o tipo de enum), considere o seguinte:
fonte
As enumerações em C ++ são como números inteiros mascarados pelos nomes que você atribui, quando você declara seus valores de enumeração (essa não é uma definição, apenas uma dica de como funciona).
Mas há dois erros no seu código:
enum
todas as minúsculasDays.
sábado antes.if (day == YourClass::Saturday){}
fonte
Eu acho que o seu problema de raiz é o uso de em
.
vez de::
, que usará o espaço para nome.Experimentar:
fonte
Days::
escopo como no seu exemplo, você deve definir a enumeraçãoenum class Days
e usar a extensão C ++ 03 + Microsoft ou C ++ 11.-std=c++98
ou-std=c++03
. Clang é bastante clara:warning: use of enumeration in a nested name specifier is a C++11 extension
.Se queremos o tipo estrito de segurança e o enum com escopo definido, o uso
enum class
é bom no C ++ 11.Se tivéssemos que trabalhar no C ++ 98, podemos usar os conselhos de
InitializeSahib
,San
para habilitar a enumeração de escopo.Se também queremos o tipo estrito de segurança, o código a seguir pode implementar algo parecido
enum
.O código é modificado a partir do exemplo Mês da classe no livro C ++ Efetivo 3º: Item 18
fonte
Primeiro, faça 'E' em enum, 'e' como minúscula.
Segundo, solte o nome do tipo 'Days' em 'Days.Saturday'.
Terceiro ... compre um bom livro em C ++.
fonte