Quando si dice enum num : char
, quindi si esprimono il fatto che num
è implementato internamente in termini di un char
ma possono ancora essere automaticamente convertito in un valore intero, che è non necessariamentechar
.
come pagina lei cita dice:
Valori di tipo enumerazione senza ambito sono implicitamente convertibile a tipi integrali.
Vedi Why does a value of an enum with a fixed underlying type of char resolve to fct(int) instead of fct(char)? per una discussione interessante sui problemi della formulazione ++ del C standard per quanto riguarda la combinazione di promozione integrale e tipi sottostanti fissi.
In ogni caso, si può immaginare tutta questa faccenda come una classe con un char
variabile membro privato e un operatore di int
conversione pubblica:
// very similar to your enum:
class num {
private:
char c;
public:
num(char c) : c(c) {}
operator int() const {
return c;
}
};
num two { '2' };
std::cout << two; // prints 50
Per aumentare la sicurezza di tipo e rendere il std::cout
linea di un errore di compilazione, basta ruotare il enum
in un enum class
:
enum class num : char
Questo è ancora simile alla immaginato class num
sopra, b ut senza l'operatore di conversione.
Quando si alimenta un'istanza di num
a std::cout
, allora sei un cliente di num
e non dovrebbero logicamente pensare che il formato di output prenderà il suo interno char
implementazione in considerazione.
Per ottenere maggiore controllo sul formato di output, è preferibile eseguire qualsiasi altro tipo personalizzato e sovraccaricare operator<<
per std::ostream
. Esempio:
#include <iostream>
enum class num : char {
zero = '0',
one = '1',
two = '2',
three = '3',
four = '4',
five = '5',
six = '6'
};
std::ostream& operator<<(std::ostream& os, num const& n)
{
switch (n)
{
case num::zero: os << "Zero"; break;
case num::one: os << "One"; break;
case num::two: os << "Two"; break;
case num::three: os << "Three"; break;
// and so on
}
return os;
}
int main()
{
std::cout << num::two; // prints "Two"
}
Naturalmente, le specifiche char
valori delle istanze enum sono ormai diventati abbastanza inutile, così si può anche sbarazzarsi di loro completamente:
enum class num : char {
zero,
one,
two,
three,
four,
five,
six
};
Questo può colpire come strano , ma tieni presente che un enum che rappresenta nient'altro che numeri generici da zero a sei non è un caso di utilizzo realistico.
[ASCII - Wikipedia] (https://en.wikipedia.org/wiki/ASCII), [tabella ASCII] (http://www.asciitable.com/) – Drop
@Drop stavo assumendo anche questo, ma allora perché 'const char two = '2';' funziona come previsto? Entrambi usano l'assegnazione di virgolette singole e questo è ciò che lo rende più confuso. –
''2' = 0x32' o 50 –