switch, case, default în C++

Alege una dintre mai multe ramuri după valoarea unei expresii întregi, a unui caracter sau a unui enum.

Sintaxă
switch (expresie) {
    case valoare1:
        ...
        break;
    case valoare2:
        ...
        break;
    default:
        ...
}

Ce face switch, case, default

switch compară valoarea expresiei cu fiecare case și sare la cel potrivit. default prinde orice altă valoare. Expresia trebuie să fie de tip întreg, char sau enum; nu merge cu std::string sau double.

După un case, execuția continuă până la primul break, chiar și în ramurile următoare (fall-through). Uneori este dorit (mai multe valori cu același cod); când este intenționat, marchează-l cu [[fallthrough]];. Ca să declari variabile într-un case, pune ramura între acolade.

Cuvântul default mai are o folosire, în clase: Clasa() = default; cere compilatorului să genereze varianta implicită a constructorului (sau a altei funcții speciale), iar auto operator<=>(const T&) const = default; generează comparațiile.

Exemple

Exemplul 1: Ziua săptămânii

#include <print>

const char* nume_zi(int zi) {
    switch (zi) {
        case 1: return "luni";
        case 2: return "marți";
        case 3: return "miercuri";
        case 4: return "joi";
        case 5: return "vineri";
        case 6:
        case 7: return "weekend";
        default: return "zi invalidă";
    }
}

int main() {
    for (int zi : {1, 5, 7, 9}) {
        std::println("{} -> {}", zi, nume_zi(zi));
    }
}

Rezultat

1 -> luni
5 -> vineri
7 -> weekend
9 -> zi invalidă

Exemplul 2: break, fall-through și blocuri

Pentru 'A' se adaugă și bonusul, apoi execuția continuă intenționat în 'B'. Ramura 'C' are acolade pentru că declară o variabilă.

#include <print>

int puncte(char calificativ) {
    int total = 0;
    switch (calificativ) {
        case 'A':
            total += 5;  // bonus
            [[fallthrough]];
        case 'B':
            total += 10;
            break;
        case 'C': {
            int partial = 6;
            total += partial;
            break;
        }
        default:
            total = 0;
    }
    return total;
}

int main() {
    std::println("A: {}, B: {}, C: {}, F: {}", puncte('A'), puncte('B'), puncte('C'), puncte('F'));
}

Rezultat

A: 15, B: 10, C: 6, F: 0

Exemplul 3: = default în clase

= default cere constructorul implicit și operatorul <=> generat de compilator, care compară membrii în ordine (C++20).

#include <compare>
#include <print>

struct Data {
    int an = 2000, luna = 1, zi = 1;
    Data() = default;
    Data(int a, int l, int z) : an(a), luna(l), zi(z) {}
    auto operator<=>(const Data&) const = default;
};

int main() {
    Data implicita;
    Data craciun(2025, 12, 25);
    std::println("Implicită: {}-{}-{}", implicita.an, implicita.luna, implicita.zi);
    std::println("Crăciunul e după: {}", craciun > implicita);
}

Rezultat

Implicită: 2000-1-1
Crăciunul e după: true

Greșeli frecvente

  • Uiți break: după ramura potrivită se execută și următoarele. Compilatorul poate avertiza (-Wimplicit-fallthrough); marchează cu [[fallthrough]] doar cazurile intenționate.
  • Încerci switch pe un std::string. Nu se compilează; folosește if/else if sau un std::map de la text la acțiune.
  • Declari o variabilă într-un case fără acolade. Compilatorul refuză („jump bypasses variable initialization”), pentru că alt case ar sări peste inițializare.

Comenzi înrudite

  • if, else: Execută un bloc de cod doar dacă o condiție este adevărată; else oferă varianta pentru cazul contrar.
  • enum: Definește un tip cu o listă fixă de valori cu nume, de exemplu zilele săptămânii sau stările unei comenzi.
  • break, continue: break oprește imediat bucla sau switch-ul curent; continue sare peste restul pasului curent și trece la următorul.
  • class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.