Μέχρι τώρα έχουμε ασχοληθεί κυρίως με αριθμούς και συμβολοσειρές. Για να μοντελοποιήσουμε τον πραγματικό κόσμο, μπορεί να θέλουμε έναν περιορισμένο αριθμό τιμών που μπορεί να πάρει μια μεταβλητή. Μπορεί να θέλεις έναν ξεχωριστό τύπο με λίγες διακριτές τιμές, καθεμία με το δικό της όνομα. Για παράδειγμα, σε ένα εργοστάσιο skateboard, το υλικό της σανίδας να είναι επιλογή μόνο ανάμεσα σε maple, bamboo ή plastic.
Θα μπορούσες να χρησιμοποιήσεις ακέραιους για να κωδικοποιήσεις αυτές τις τιμές, αλλά θα έπρεπε να γράψεις επιπλέον κώδικα για να ελέγχεις αν έρχεται από το σύστημα κάποια μη έγκυρη τιμή για το υλικό.
Η σημασία αυτών των μαγικών αριθμών είναι δύσκολο να εντοπιστεί μέσα στον πηγαίο κώδικα και εύκολα προκαλούν μπερδέματα.
Οι enumerations μπορούν να χρησιμοποιηθούν για να ενθαρρύνουν εκφραστικό κώδικα και να περιορίσουν τις συγκρίσεις που γίνονται κατά λάθος.
Ο ειδικός όρος για αυτού του είδους την απαρίθμηση είναι scoped enumeration.
Το παρακάτω απόσπασμα δείχνει πώς να γράψεις μια DeckMaterial enumeration.
Πρόσεξε τη λέξη-κλειδί enum class και το ; στο τέλος του ορισμού:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
Τώρα, κοίτα μια συνάρτηση τιμολόγησης στο κατάστημα skateboard και πρόσεξε τον τελεστή προσδιορισμού εμβέλειας (::) που προσδιορίζει έναν enumerator της enumeration:
double deck_price(double base_price, DeckMaterial material) {
if(material == DeckMaterial::plastic) {
return base_price * 0.9;
}
return base_price * 1.3;
}
Φαντάσου ότι έχεις μια δεύτερη enumeration για το υλικό των τροχών:
enum class WheelMaterial {
steel,
clay,
plastic
};
Αν και τόσο οι τροχοί όσο και η σανίδα μπορούν να είναι από plastic, τα δύο δεν μπορούν να μπερδευτούν.
Είναι διαφορετικοί τύποι: DeckMaterial plastic και WheelMaterial plastic.
Κάθε enumeration θα έχει τους enumerators της στη δική της εμβέλεια, στον δικό της namespace.
Γι' αυτόν τον λόγο ονομάζονται scoped enumerations.
Μπορεί να σκέφτεσαι ότι με ένα όνομα σαν το scoped, θα υπάρχουν και unscoped απαριθμήσεις, και θα είχες δίκιο.
Οι Unscoped enumerations γίνονται όλο και λιγότερο δημοφιλείς επειδή μοιράζονται όλες τον ίδιο καθολικό χώρο ονομάτων.
Εξαιτίας αυτού του μοιράσματος, δεν θα μπορούσες να έχεις δύο unscoped enumerations με τους ίδιους enumerators, όπως το plastic στο παραπάνω παράδειγμα.
Επίσης, οι unscoped enumerations μετατρέπονται σιωπηρά σε ακέραιους.
Κοίτα το παρακάτω παράδειγμα για ένα αναπάντεχο αποτέλεσμα:
enum CitrusFruits {
lemons, // 0
oranges, //1
};
enum IceCream {
walnut, // 0
apples, // 1
};
bool comparison{apples == oranges};
// => true
// Example from above:
bool comparison{DeckMaterial::plastic == WheelMaterial::plastic};
// => Does not compile!
Αν θέλεις να μετατρέψεις τις scoped enumerations σε ακέραιους, μπορείς να χρησιμοποιήσεις το static_cast<int>.