As instruções switch devem sempre conter uma cláusula padrão?


255

Em uma das minhas primeiras revisões de código (um tempo atrás), me disseram que é uma boa prática incluir uma cláusula padrão em todas as instruções de opção. Recentemente, lembrei-me deste conselho, mas não me lembro qual era a justificativa. Parece bastante estranho para mim agora.

  1. Existe uma razão sensata para sempre incluir uma declaração padrão?

  2. Este idioma depende? Não me lembro qual idioma eu estava usando na época - talvez isso se aplique a alguns idiomas e não a outros?


9
Vai ser em um grau grande dependente de idioma
skaffman

Respostas:


277

Os casos de troca quase sempre devem ter um defaultcaso.

Razões para usar um default

1.Para 'pegar' um valor inesperado

switch(type)
{
    case 1:
        //something
    case 2:
        //something else
    default:
        // unknown type! based on the language,
        // there should probably be some error-handling
        // here, maybe an exception
}

2. Para lidar com ações 'padrão', onde os casos são para comportamento especial.

Você vê muito isso em programas orientados a menus e em scripts do shell bash. Você também pode ver isso quando uma variável é declarada fora da caixa de seleção, mas não inicializada, e cada caso a inicializa para algo diferente. Aqui, o padrão também precisa inicializá-lo para que o código de linha que acessa a variável não apresente erro.

3. Para mostrar a alguém lendo seu código que você cobriu esse caso.

variable = (variable == "value") ? 1 : 2;
switch(variable)
{
    case 1:
        // something
    case 2:
        // something else
    default:
        // will NOT execute because of the line preceding the switch.
}

Este foi um exemplo simplificado demais, mas o ponto é que alguém que lê o código não deve se perguntar por variableque não pode ser algo diferente de 1 ou 2.


O único caso em que posso pensar em NÃO usar defaulté quando o switch está verificando algo em que é óbvio que todas as outras alternativas podem ser ignoradas com alegria

switch(keystroke)
{
    case 'w':
        // move up
    case 'a':
        // move left
    case 's':
        // move down
    case 'd':
        // move right
    // no default really required here
}

26
Seu exemplo sobre pressionamentos de teclas meio que contradiz o resto do que você acabou de dizer. : | Eu acho que um pouco mais de explicação faria sentido, como: você não se importa com um padrão nesse caso, porque se outra tecla for pressionada, você não se importa, mas se uma variável é passada é diferente do esperado, nós nos importamos. .
Andrew

1
Ao mesmo tempo, se você estiver verificando um parâmetro GET, poderá não ser uma exceção lançada toda vez que um usuário alterar o URL de obtenção para algo que não é válido: [
Andrew

4
O @Andrew WASD é comum para movimentos de personagens de jogos de computador. Você não precisa de nenhuma ação padrão, pois outras teclas podem ser atribuídas a outras interações. Nesse tipo de comutador, é bom chamar funções de movimento.
21416 jemiloii

13
Alguns compiladores avisam ao ativar uma enum se um caso estiver faltando e a adição de um caso padrão suprimirá esse aviso. Dado que esta é na minha experiência uma fonte muito comum de erro (esquecendo-se de atualizar a algum lugar interruptor depois um valor de enumeração é adicionado), esta parece ser uma muito boa razão para omitir um caso padrão.
Rdb

3
@virusrocks Se a sua condição for um enum, você ainda poderá ter valores inesperados. Por exemplo, se você adicionar um novo valor à enumeração e esquecer de atualizar uma opção. Além disso, em alguns idiomas, você pode atribuir valores inteiros a enumerações. Em C ++ enum MyEnum { FOO = 0, BAR = 1 }; MyEnum value = (MyEnum)2;cria uma MyEnuminstância válida que não é igual a FOOou BAR. Se um desses problemas causar um erro no seu projeto, um caso padrão o ajudará a encontrar o erro muito rapidamente, geralmente sem a necessidade de depurador!
cdgraham

54

Não.

E se não houver ação padrão, o contexto é importante. E se você quiser apenas agir com alguns valores?

Veja o exemplo da leitura de teclas pressionadas para um jogo

switch(a)
{
   case 'w':
     // Move Up
     break;
   case 's':
     // Move Down
     break;
   case 'a':
     // Move Left
     break;
   case 'd':
     // Move Right
     break;
}

Adicionando:

default: // Do nothing

É apenas uma perda de tempo e aumenta a complexidade do código sem motivo.


14
Bom exemplo. Mas, de fato, adicionar uma cláusula padrão com um simples // do nothingcomentário deixa claro que está 'ok' se nem todos os casos forem cobertos, em oposição a outras instruções de opção em que isso seria 'não está ok'.
The Nail

8
Não. A codificação não consiste apenas em lidar com alguns casos. Também serve como um documento. Escrevendo default: e comentando como // não faz nada ou mais nada, a legibilidade do código se torna melhor.
JongAm Park

22
Discordo dos outros comentários. Adicionar padrão // Do not nothing adiciona muito pouco, a menos que você não saiba como o código funciona. Eu posso olhar para uma instrução switch sem um padrão e sei que o padrão é não fazer nada. Adicionar desordem não torna isso mais óbvio.
21815 Robert Noack

Exatamente. É o mesmo conceito de entregar todos os parâmetros posteriores. Você lida com quem você gosta e não com os outros.
21716 Jimmy Kane

2
@jybrd Se você não acredita que o desenvolvedor anterior tenha deixado de fora o padrão intencionalmente, por que você confiaria que eles estavam corretos ao colocá-lo? Um padrão pode ser acidentalmente vazio, tão fácil quanto desaparecer completamente. Um comentário não é necessário para algo tão trivial. Isso é confusão de código. Faça testes de unidade de cobertura total para mostrar suas intenções. (Apenas minha opinião)
Robert Noack 03/03

45

NÃO ter o caso padrão pode realmente ser benéfico em algumas situações.

Se seus casos de opção forem valores de enumeração, por não ter um caso padrão, você poderá receber um aviso do compilador se estiver faltando algum caso. Dessa forma, se novos valores de enumeração forem adicionados no futuro e você esquecer de adicionar casos para esses valores na opção, poderá descobrir o problema no momento da compilação. Você ainda deve garantir que o código execute a ação apropriada para valores não manipulados, caso um valor inválido tenha sido convertido para o tipo de enumeração. Portanto, isso pode funcionar melhor em casos simples em que você pode retornar dentro do caso enum em vez de interromper.

enum SomeEnum
{
    ENUM_1,
    ENUM_2,
    // More ENUM values may be added in future
};

int foo(SomeEnum value)
{
    switch (value)
    {
    case ENUM_1:
        return 1;
    case ENUM_2:
        return 2;
    }
    // handle invalid values here
    return 0;
 }

Esta é uma observação importante! Aplica-se ainda mais em Java porque não permite converter ints para enumerações.
Lii

2
No seu exemplo, você pode lançar uma exceção em vez de retornar após a instrução switch. Dessa forma, você pode ter a verificação estática do compilador e obter um erro claro se algo inesperado acontecer.
Lii

1
Concordo. No Swift, por exemplo, o switch deve ser exaustivo, caso contrário, você receberá um erro do compilador! Fornecer um padrão apenas silencia esse erro útil. Por outro lado, fornecer um padrão se todos os casos forem tratados realmente lança um aviso do compilador (instrução inacessível).
217 Andy

1
Foi corrigido apenas um bug que causaria um aviso do compilador se não houvesse padrão: portanto, geralmente uma variável Switch over enum não deve ter padrão.
Notan

42

Eu sempre usaria uma cláusula padrão, independentemente do idioma em que você está trabalhando.

As coisas podem dar errado. Valores não serão o que você espera, e assim por diante.

Não querer incluir uma cláusula padrão implica que você está confiante de que conhece o conjunto de valores possíveis. Se você acredita que conhece o conjunto de valores possíveis, se o valor estiver fora desse conjunto de valores possíveis, convém ser informado - é certamente um erro.

Essa é a razão pela qual você deve sempre usar uma cláusula padrão e gerar um erro, por exemplo, em Java:

switch (myVar) {
   case 1: ......; break;
   case 2: ......; break;
   default: throw new RuntimeException("unreachable");
}

Não há razão para incluir mais informações do que apenas a string "inacessível"; se isso realmente acontecer, você precisará examinar a origem e os valores das variáveis, etc. de qualquer maneira, eo rastreamento de pilha de exceção incluirá esse número de linha, portanto, não será necessário perder tempo escrevendo mais texto na mensagem de exceção.


39
Eu preferiria, throw new RuntimeException("myVar invalid " + myVar);pois isso pode fornecer informações suficientes para descobrir e corrigir o erro sem a necessidade de usar um depurador e inspecionar variáveis, o que pode ser difícil se esse for um problema que raramente ocorre e é difícil de reproduzir.
Chris Dodd

1
E se não for uma condição de erro para o valor não corresponder a um dos casos?
Gabe

4
Se não for uma condição de erro, não haverá necessidade de a default:. Porém, mais frequentemente, não se observa um padrão, porque se pensa myVarque nunca poderá ter outro valor além dos listados; no entanto, não posso contar o número de vezes que fiquei surpreso na vida real quando a variável teve um valor diferente dos valores que "poderia" ter. Nesses casos, sou grato pela exceção, fazendo-me ver isso imediatamente, em vez de causar outro erro mais tarde (mais difícil de depurar) ou resposta errada (pode ser ignorada nos testes).
Adrian Smith

2
Eu concordo com Adrian. Falhar duro e falhar cedo.
Slappy

Eu prefiro jogar um em AssertionErrorvez de RuntimeException, pois essa situação é muito semelhante a uma afirmação afirmando que myVaré um dos valores manipulados. Também a chance de alguém pegar e engolir o erro é menor.
Philipp Wendler

15

Na minha empresa, escrevemos software para o mercado de aviônicos e de defesa e sempre incluímos uma declaração padrão, porque TODOS os casos em uma declaração de chave devem ser explicitamente tratados (mesmo que seja apenas um comentário dizendo 'Não faça nada'). Não podemos pagar pelo software apenas para se comportar mal ou simplesmente travar com valores inesperados (ou mesmo o que pensamos impossíveis).

Pode-se discutir que um caso padrão nem sempre é necessário, mas, ao exigir sempre, é facilmente verificado pelos nossos analisadores de código.


1
Eu tenho o mesmo requisito em que trabalho; escrevemos código para os µControllers incorporados que precisam passar por rigorosas verificações de segurança e geralmente são submetidos a EMI. Seria irresponsável assumir que uma variável enumerada nunca terá um valor que não esteja na lista de enumeração.
Oosterwal

12

Uma instrução "switch" deve sempre incluir uma cláusula padrão? Não. Deve normalmente incluem um padrão.

A inclusão de uma cláusula padrão só faz sentido se houver algo a fazer, como afirmar uma condição de erro ou fornecer um comportamento padrão. Incluir um "apenas porque" é uma programação de cultos de carga e não oferece valor. É o equivalente "switch" de dizer que todas as declarações "if" devem incluir um "else".

Aqui está um exemplo trivial de onde não faz sentido:

void PrintSign(int i)
{
    switch (Math.Sign(i))
    {
    case 1:
        Console.Write("positive ");
        break;
    case -1:
        Console.Write("negative ");
        break;
    default: // useless
    }
    Console.Write("integer");
}

Isso é equivalente a:

void PrintSign(int i)
{
    int sgn = Math.Sign(i);
    if (sgn == 1)
        Console.Write("positive ");
    else if (sgn == -1)
        Console.Write("negative ");
    else // also useless
    {
    }
    Console.Write("integer");
}

Discordo. IMHO, a única vez que um padrão não deveria existir é se não há como, por enquanto e sempre, que o conjunto de entradas possa mudar, e você tenha todo o valor possível coberto. O caso mais simples que consigo pensar é um valor booleano de um banco de dados, onde as únicas respostas (até que o SQL mude!) São verdadeiras, falsas e NULL. Em qualquer outro caso, ter um padrão com uma asserção ou exceção de "Não deveria acontecer!" faz muito sentido. Se o seu código for alterado e você tiver um ou mais novos valores, poderá garantir a codificação para eles, e seus testes serão ampliados se você não o fizer.
Harper Shelby

4
@ Harper: Seu exemplo se enquadra na categoria "afirmar uma condição de erro".
Gabe

Eu diria que meu exemplo é a norma e que o pequeno número de casos em que se pode ter 100% de certeza de que todos os casos possíveis são cobertos e que um padrão não é necessário é a exceção. Sua resposta é redigida de uma maneira que soa (pelo menos para mim) como se o padrão de não fazer nada acontecer mais frequentemente.
Harper Shelby

@ Harper: OK, mudei a redação para indicar que a situação de não fazer nada é menos comum.
Gabe

4
Eu acho que a default:nesses casos codifica suas suposições. Por exemplo, não há problema em sgn==0imprimir integer(nem positivo nem negativo), ou isso é um erro? Para mim, lendo esse código, é difícil dizer. Suponho que você não queira escrever zeronesse caso integere que o programador assumiu que sgnsó pode ser -1 ou +1. Se fosse esse o caso, default:permitir que o programador capturasse o erro de suposição mais cedo e alterasse o código.
Adrian Smith

7

Tanto quanto eu vejo, a resposta é 'padrão' é opcional, dizer que um comutador deve sempre conter um padrão é como dizer que todo 'if-elseif' deve conter um 'else'. Se houver uma lógica a ser executada por padrão, a instrução 'default' deverá estar lá, mas, caso contrário, o código poderá continuar em execução sem fazer nada.


6

Ter uma cláusula padrão quando não é realmente necessário é programação defensiva Isso geralmente leva a códigos excessivamente complexos por causa de muito código de manipulação de erros. Esse código de manipulação e detecção de erros prejudica a legibilidade do código, dificulta a manutenção e, eventualmente, leva a mais erros do que resolve.

Portanto, acredito que se o padrão não for atingido - você não precisará adicioná-lo.

Observe que "não deve ser alcançado" significa que, se atingido, é um erro no software - você precisa testar valores que podem conter valores indesejados devido à entrada do usuário, etc.


3
Outro motivo comum para obter casos inesperados: outras partes do código são modificadas, talvez anos depois.
Hendrik Brummermann 11/03/11

De fato, esse é um comportamento muito perigoso. Pelo menos, eu adicionaria uma cláusula assert (). Em seguida, é facilmente detectado sempre que houver um bug.
Kurt Pattyn

5

Eu diria que depende do idioma, mas em C, se você estiver ativando um tipo de enum e manipular todos os valores possíveis, provavelmente será melhor NÃO incluir um caso padrão. Dessa forma, se você adicionar uma tag enum adicional posteriormente e esquecer de adicioná-la ao comutador, um compilador competente emitirá um aviso sobre o caso ausente.


5
É improvável que "todo valor possível" seja tratado com enumerações. Você pode converter um número inteiro em uma enumeração mesmo que esse valor específico não esteja explicitamente definido. E qual compilador adverte sobre o caso ausente?
TrueWill 10/03/11

1
@TrueWill: Sim, você pode usar conversões explícitas para escrever código ofuscado que é impossível de entender; para escrever código compreensível, você deve evitar isso. gcc -Wall(tipo do menor denominador comum de compiladores competentes) emite avisos sobre enumerações não tratadas nas instruções do switch.
22412 Chris Dodd

4

Se você souber que a instrução switch só terá um conjunto estritamente definido de rótulos ou valores, faça isso para cobrir as bases, para obter sempre resultados válidos. Basta colocar o padrão sobre o rótulo que programaticamente / logicamente ser o melhor manipulador para outros valores.

switch(ResponseValue)
{
    default:
    case No:
        return false;
    case Yes;
        return true;
}

O cólon defaultainda é necessário aqui? Ou isso permite alguma sintaxe especial que lhe permitiu omitir?
Ponkadoodle

O cólon é obrigatório, isso foi um erro de digitação, obrigado por chamar minha atenção.
deegee

3

Pelo menos não é obrigatório em Java. De acordo com a JLS, diz que pelo menos um caso padrão pode estar presente. O que significa que nenhum caso padrão é aceitável. Às vezes, também depende do contexto em que você está usando a instrução switch. Por exemplo, em Java, o seguinte bloco de opções não requer maiúsculas e minúsculas padrão

private static void switch1(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        break;
    case "Tuesday":
        System.out.println("Tuesday");
        break;
    }
}

Mas no método a seguir, que espera retornar uma String, o caso padrão é útil para evitar erros de compilação

    private static String switch2(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        return name;

    case "Tuesday":
        System.out.println("Tuesday");
        return name;

    default:
        return name;
    }
}

embora você possa evitar erros de compilação para o método acima sem ter uma caixa padrão, basta ter uma declaração de retorno no final, mas fornecer uma caixa padrão torna mais legível.


3

Algumas diretrizes (desatualizadas) dizem isso, como MISRA C :

O requisito para uma cláusula padrão final é a programação defensiva. Esta cláusula deve tomar as medidas apropriadas ou conter um comentário adequado sobre o motivo pelo qual nenhuma ação foi tomada.

Esse conselho está desatualizado porque não se baseia nos critérios atualmente relevantes. A omissão flagrante é o que Harlan Kassler disse:

Deixar de fora o caso padrão permite que o compilador avise ou falhe opcionalmente quando vir um caso não tratado. Afinal, a verificação estática é melhor do que qualquer verificação dinâmica e, portanto, não é um sacrifício digno para quando você também precisa da verificação dinâmica.

Como Harlan também demonstrou, o equivalente funcional de um caso padrão pode ser recriado após a troca. O que é trivial quando cada caso é um retorno antecipado.

A necessidade típica de uma verificação dinâmica é a manipulação de entrada, em um sentido amplo. Se um valor vier de fora do controle do programa, ele não será confiável.

É também aqui que Misra assume o ponto de vista da programação defensiva extrema, pela qual, desde que um valor inválido seja fisicamente representável, ele deve ser verificado, independentemente de o programa estar comprovadamente correto. O que faz sentido se o software precisar ser o mais confiável possível na presença de erros de hardware. Mas como Ophir Yoktan disse, a maioria dos softwares é melhor não "manipular" bugs. A última prática é às vezes chamada de programação ofensiva .


2

Você deve ter um padrão para capturar valores não esperados chegando.

No entanto, discordo de Adrian Smith de que sua mensagem de erro por padrão deve ser algo totalmente sem sentido. Pode haver um caso não tratado que você não viu (o que é o ponto) que o usuário acabará vendo e uma mensagem como "inacessível" é totalmente inútil e não ajuda ninguém nessa situação.

Caso em questão, quantas vezes você teve um BSOD totalmente sem sentido? Ou uma exceção fatal @ 0x352FBB3C32342?


por exemplo - lembre-se de que não é apenas o desenvolvedor que sempre vê mensagens de erro. Vivemos no mundo real, as pessoas cometem erros.
John Hunt

2

Se o valor da chave ( chave (variável )) não atingir o caso padrão, o caso padrão não será necessário. Mesmo se mantivermos o caso padrão, ele não será executado. É um código morto.


2

É uma 'convenção' de codificação opcional. Dependendo do uso, é necessário ou não. Pessoalmente, acredito que se você não precisar, não deverá estar lá. Por que incluir algo que não será usado ou alcançado pelo usuário?

Se as possibilidades de maiúsculas e minúsculas são limitadas (ou seja, um booleano), a cláusula padrão é redundante !


2

Se não houver um caso padrão em uma switchinstrução, o comportamento poderá ser imprevisível se esse caso surgir em algum momento, o que não era previsível no estágio de desenvolvimento. É uma boa prática incluir um defaultcaso.

switch ( x ){
  case 0 : { - - - -}
  case 1 : { - - - -}
}

/* What happens if case 2 arises and there is a pointer
* initialization to be made in the cases . In such a case ,
* we can end up with a NULL dereference */

Tal prática pode resultar em um erro como desreferência NULL , vazamento de memória e outros tipos de erros graves .

Por exemplo, assumimos que cada condição inicializa um ponteiro. Mas se o defaultcaso deve surgir e se não inicializarmos nesse caso, há toda a possibilidade de aparecer uma exceção de ponteiro nulo. Portanto, é sugerido o uso de uma defaultdeclaração de caso, mesmo que possa ser trivial.


2

O caso padrão pode não ser necessário no comutador usado pelo enum. Quando switch contiver todo o valor, o caso padrão nunca será executado. Portanto, neste caso, não é necessário.


1

Depende de como o switch em um determinado idioma funciona, no entanto, na maioria dos idiomas, quando nenhum caso é correspondido, a execução é executada na instrução switch sem aviso. Imagine que você esperou algum conjunto de valores e os manipulou no switch, mas obtém outro valor na entrada. Nada acontece e você não sabe que nada aconteceu. Se você pegasse o caso por padrão, saberia que havia algo errado.


1

Discordo da resposta mais votada de Vanwaril acima.

Qualquer código adiciona complexidade. Também testes e documentação devem ser feitos para isso. Portanto, é sempre bom se você pode programar usando menos código. Minha opinião é que eu uso uma cláusula padrão para declarações de chave não exaustivas, enquanto eu não uso cláusula padrão para declarações de chave exaustivas. Para ter certeza de que fiz direito, use uma ferramenta de análise de código estática. Então, vamos entrar nos detalhes:

  1. Instruções de chave não exaustivas: essas devem sempre ter um valor padrão. Como o nome sugere, são declarações que não cobrem todos os valores possíveis. Isso também pode não ser possível, por exemplo, uma instrução switch em um valor inteiro ou em uma String. Aqui eu gostaria de usar o exemplo de Vanwaril (deve-se mencionar que acho que ele usou esse exemplo para fazer uma sugestão errada. Eu o uso aqui para indicar o oposto -> Usar uma declaração padrão):

    switch(keystroke)
    {
      case 'w':
        // move up
      case 'a':
        // move left
      case 's':
        // move down
      case 'd':
        // move right
      default:          
        // cover all other values of the non-exhaustive switch statement
    }
    

    O jogador pode pressionar qualquer outra tecla. Então não poderíamos fazer nada (isso pode ser mostrado no código apenas adicionando um comentário ao caso padrão) ou, por exemplo, deve imprimir algo na tela. Este caso é relevante, pois pode acontecer.

  2. Instruções de chave exaustivas: Essas instruções de chave cobrem todos os valores possíveis, por exemplo, uma declaração de chave em uma enumeração de tipos de sistema de notas. Ao desenvolver código pela primeira vez, é fácil cobrir todos os valores. No entanto, como somos humanos, há uma pequena chance de esquecer alguns. Além disso, se você adicionar um valor de enum posteriormente, de modo que todas as instruções de opção tenham que ser adaptadas para torná-las exaustivas novamente, abrirá o caminho para o erro. A solução simples é uma ferramenta de análise de código estática. A ferramenta deve verificar todas as instruções de opção e verificar se são exaustivas ou se têm um valor padrão. Aqui está um exemplo para uma declaração exaustiva de chave. Primeiro, precisamos de um enum:

    public enum GradeSystemType {System1To6, SystemAToD, System0To100}
    

    Então precisamos de uma variável desse enum como GradeSystemType type = .... Uma declaração de switch exaustiva seria assim:

    switch(type)
    {
      case GradeSystemType.System1To6:
        // do something
      case GradeSystemType.SystemAToD:
        // do something
      case GradeSystemType.System0To100:
        // do something
    }
    

    Portanto, se estendermos o GradeSystemTypeby, por exemplo, System1To3a ferramenta de análise de código estático deve detectar que não há cláusula padrão e a instrução switch não é exaustiva, portanto, estamos salvos.

Apenas mais uma coisa. Se sempre usarmos uma defaultcláusula, pode acontecer que a ferramenta de análise de código estático não seja capaz de detectar instruções de chave exaustivas ou não exaustivas, pois sempre detecta a defaultcláusula. Isso é muito ruim, pois não seremos informados se estendermos o enum por outro valor e esquecermos de adicioná-lo a uma instrução switch.


0

As instruções switch devem sempre conter uma cláusula padrão? Nenhum caso de comutação pode existir sem o caso padrão; no caso de comutador, o caso padrão acionará o valor do comutador switch(x)neste caso x quando não corresponder a nenhum outro valor de caso.


0

Acredito que isso seja bastante específico da linguagem e, para o caso C ++, um ponto menor para o tipo de classe enum . O que parece mais seguro que o C enum tradicional. MAS

Se você observar a implementação do std :: byte, é algo como:

enum class byte : unsigned char {} ;

Fonte: https://en.cppreference.com/w/cpp/language/enum

E considere também isso:

Caso contrário, se T for um tipo de enumeração com escopo definido ou sem escopo, com tipo subjacente fixo, e se a lista-init-braced tiver apenas um inicializador, e se a conversão do inicializador para o tipo subjacente for sem restrição, e se a inicialização é de lista direta, e a enumeração é inicializada com o resultado da conversão do inicializador em seu tipo subjacente.

(desde C ++ 17)

Fonte: https://en.cppreference.com/w/cpp/language/list_initialization

Este é um exemplo de classe enum que representa valores que não são enumeradores definidos. Por esse motivo, você não pode confiar totalmente em enumerações. Dependendo da aplicação, isso pode ser importante.

No entanto, eu realmente gosto do que @Harlan Kassler disse em seu post e vou começar a usar essa estratégia em algumas situações.

Apenas um exemplo de classe enum não segura:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.