std::exception în C++

Clasa de bază a tuturor excepțiilor din biblioteca standard; what() returnează mesajul erorii.

Sintaxă
#include <exception>
class exception {
public:
    virtual const char* what() const noexcept;
};

Ce face std::exception

Toate excepțiile aruncate de biblioteca standard moștenesc std::exception: std::runtime_error, std::out_of_range, std::bad_alloc etc. De aceea un singur catch (const std::exception& e) le prinde pe toate.

Metoda virtuală what() returnează un text care descrie eroarea. Pentru excepțiile standard, textul este cel dat la aruncare (throw std::runtime_error("mesaj")) sau unul ales de bibliotecă.

Excepțiile se prind mereu prin referință const (const std::exception&). Prinse prin valoare, ar fi copiate și „tăiate” la tipul de bază (object slicing), iar what() ar pierde mesajul specific. Pentru sintaxa try/catch/throw, vezi paginile acestor cuvinte cheie.

Ce returnează

what() returnează un const char* cu mesajul erorii.

Exemple

Exemplul 1: Un singur catch pentru toate erorile standard

Textele pentru vector::at și stoi sunt alese de biblioteca standard (aici libc++) și pot diferi la alte compilatoare.

#include <exception>
#include <print>
#include <stdexcept>
#include <string>
#include <vector>

void incearca(int caz) {
    try {
        if (caz == 1) {
            std::vector<int> v{1, 2, 3};
            std::println("{}", v.at(10));
        } else if (caz == 2) {
            std::println("{}", std::stoi("doisprezece"));
        } else {
            throw std::runtime_error("serverul nu răspunde");
        }
    } catch (const std::exception& e) {
        std::println("Eroare la cazul {}: {}", caz, e.what());
    }
}

int main() {
    for (int caz = 1; caz <= 3; ++caz) incearca(caz);
}

Rezultat

Eroare la cazul 1: vector
Eroare la cazul 2: stoi: no conversion
Eroare la cazul 3: serverul nu răspunde

Exemplul 2: Excepție proprie care moștenește std::exception

#include <exception>
#include <print>
#include <string>

class StocInsuficient : public std::exception {
public:
    StocInsuficient(std::string produs, int disponibil)
        : mesaj_("Stoc insuficient pentru " + produs + " (disponibil: " + std::to_string(disponibil) + ")") {}
    const char* what() const noexcept override { return mesaj_.c_str(); }
private:
    std::string mesaj_;
};

void comanda(int cantitate) {
    const int stoc = 3;
    if (cantitate > stoc) throw StocInsuficient("cafea", stoc);
    std::println("Comandă acceptată: {} buc.", cantitate);
}

int main() {
    try {
        comanda(2);
        comanda(5);
    } catch (const std::exception& e) {
        std::println("{}", e.what());
    }
}

Rezultat

Comandă acceptată: 2 buc.
Stoc insuficient pentru cafea (disponibil: 3)

Greșeli frecvente

  • Prinzi excepția prin valoare: catch (std::exception e). Obiectul este „tăiat” la clasa de bază și what() dă un mesaj generic. Scrie catch (const std::exception& e).
  • Pui catch (const std::exception&) înaintea unui catch pentru o clasă derivată. Blocurile se verifică în ordine, deci cel specific nu mai este atins niciodată; pune întâi excepțiile specifice.

Comenzi înrudite

  • try, catch: try marchează codul care poate arunca o excepție, iar blocurile catch prind și tratează excepțiile de un anumit tip.
  • throw: Aruncă o excepție: oprește execuția normală și trimite eroarea la cel mai apropiat catch potrivit.
  • std::runtime_error: Excepție pentru erorile care apar doar la rulare, din cauze externe: fișier lipsă, rețea, date greșite.
  • noexcept: Marchează o funcție care promite că nu aruncă excepții; ca operator, verifică la compilare dacă o expresie poate arunca.