Enumerări
Enumerările (enum) reprezintă o altă modalitate de a defini tipuri proprii. Caracteristica lor distinctivă este faptul că ele conțin un set de constante numerice. O enumerare are următoarea formă:
enum class nume_enumerare { constanta_1, constanta_2, ... constanta_N };
După cuvintele cheie enum class urmează numele enumerării, iar apoi, între acolade, sunt enumerate constantele, separate prin virgulă.
Să definim o enumerare simplă:
enum class Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
În acest caz, enumerarea se numește Day și reprezintă zilele săptămânii. Între acolade sunt toate zilele săptămânii. De fapt, ele reprezintă constante numerice.
Fiecărei constante i se asociază o anumită valoare numerică. Implicit, prima constantă primește valoarea 0, iar următoarele cresc cu câte 1. Astfel, în exemplul de mai sus, Monday va avea valoarea 0, Tuesday – 1 și așa mai departe. Prin urmare, ultima constantă – Sunday va fi egală cu 6.
După crearea enumerării, putem defini o variabilă de acest tip și să îi atribuim una dintre constante:
Day today {Day::Thursday};
// sau
//Day today = Day::Thursday;
În acest caz, se definește variabila today, care este egală cu Day::Thursday, adică a patra constantă din enumerarea Day.
Pentru a afișa valoarea variabilei în consolă, se poate folosi conversia la tipul int:
#include <iostream>
enum class Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
int main()
{
Day today {Day::Thursday};
std::cout << "Today: " << static_cast<int>(today) << std::endl;
}
Astfel, în consolă se va afișa Today: 3, deoarece constanta Thursday are valoarea 3.
Putem controla și valorile constantelelor din enumerare. De exemplu, putem seta o valoare de început pentru o constantă, iar celelalte vor crește automat:
enum class Day {Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
În acest caz, Tuesday va avea valoarea 2, iar Sunday – 7.
Putem seta valori individuale pentru fiecare constantă sau combina acest mod cu incrementarea automată:
enum class Day {Monday = 2, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = 1};
Aici, Saturday va avea valoarea 7, iar Sunday – 1.
Este posibil să atribuim aceeași valoare la două constante:
enum class Day {Monday = 1, Mon = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
Aici, constantele Monday și Mon au aceeași valoare.
Putem atribui constantelor și valori bazate pe altele deja definite:
enum class Day {Monday = 1, Mon = Monday, Tuesday = Monday + 1, Wednesday, Thursday, Friday, Saturday, Sunday};
Este important de știut că valorile constantelor dintr-o enumerare trebuie să fie valori integrale constante. Totuși, putem alege alt tip întreg, de exemplu char:
enum class Operation: char {Add = '+', Subtract = '-', Multiply = '*'};
Dacă dorim să afișăm aceste valori ca simboluri, trebuie să le convertim în char:
#include <iostream>
enum class Operation: char {Add = '+', Subtract='-', Multiply='*'};
int main()
{
std::cout << "add: " << static_cast<char>(Operation::Add) << std::endl;
std::cout << "subtracte: " << static_cast<char>(Operation::Subtract) << std::endl;
std::cout << "multiply: " << static_cast<char>(Operation::Multiply) << std::endl;
}
Utilizarea enumerărilor
Enumerările sunt utile atunci când trebuie să păstrăm un set limitat de stări și, în funcție de starea curentă, să executăm anumite acțiuni. De exemplu:
#include <iostream>
enum class Operation {Add, Subtract, Multiply};
void calculate(int n1, int n2, Operation op)
{
switch (op)
{
case Operation::Add:
std::cout << n1 + n2 << std::endl;
break;
case Operation::Subtract:
std::cout << n1 - n2 << std::endl;
break;
case Operation::Multiply:
std::cout << n1 * n2 << std::endl;
break;
}
}
int main()
{
calculate(10, 6, Operation::Add); // 16
calculate(10, 6, Operation::Subtract); // 4
calculate(10, 6, Operation::Multiply); // 60
}
Aici, toate operațiile aritmetice sunt stocate în enumerarea Operation. În funcția calculate, în funcție de valoarea celui de-al treilea parametru – operația aplicată – sunt efectuate anumite acțiuni cu primii doi parametri.
Importarea constantelor din enumerare
În mod implicit, pentru a accesa constantele unei enumerări, trebuie să specificăm numele enumerării, de exemplu Day::Monday. Însă, începând cu standardul C++20, putem importa constantele în contextul curent folosind operatorul using.
using enum Day;
Și apoi putem folosi doar numele constantelor:
#include <iostream>
enum class Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
using enum Day; // importăm constantele în domeniul de vizibilitate curent
int main()
{
Day today {Thursday}; // folosim doar numele constantei
// sau
//Day today = Thursday;
std::cout << static_cast<int>(today) << std::endl; // 3
std::cout << static_cast<int>(Sunday) << std::endl; // 6
}
De asemenea, putem importa o singură constantă:
using Day::Monday; // importăm doar Monday
// ...
Day today {Monday};
În acest caz, doar constanta Day::Monday este disponibilă fără prefix. Pentru celelalte constante, trebuie în continuare să folosim numele enumerării.
Deoarece această funcționalitate este disponibilă doar din standardul C++20, la compilare cu g++ sau clang++ trebuie adăugat flagul:
-std=c++20
Enumerări în stil C
Trebuie menționat că anterior în C++ era utilizată o altă formă de enumerări, moștenită din limbajul C, și definită fără cuvântul cheie class:
#include <iostream>
enum Day {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
int main()
{
Day today = Tuesday;
std::cout << today << std::endl; // 1
}
Astfel de enumerări se mai numesc unscoped (neîncadrate într-un domeniu). Aceste enumerări pot fi întâlnite în programele mai vechi. Totuși, pentru că pot duce mai ușor la erori, această formă este folosită tot mai rar în prezent.