stdexcept class (tsz. stdexcept classes)
<stdexcept>
és <exception>
fejlécben definiált osztályhierarchia. Ezek az osztályok egységes felületet biztosítanak a futás közbeni hibák jelzéséhez és kezeléséhez, valamint segítik a kód olvashatóságát és karbantarthatóságát. Ebben a szövegben részletesen áttekintjük a legfontosabb osztályokat, azok viszonyát, használatát, testreszabását, és a hozzájuk kapcsolódó legjobb gyakorlatokat.
A C++-ban minden kivétel típusa implicit módon vagy expliciten örökli az alap osztálytól, a std::exception
-től (definiálva a <exception>
-ben). A <stdexcept>
fejléc kiegészíti ezt további specializált osztályokkal, hogy a különböző hibajelenségekhez megfelelően tükröződő típusokat kínáljon.
std::exception ├─ std::logic_error │ ├─ std::invalid_argument │ ├─ std::domain_error │ ├─ std::length_error │ └─ std::out_of_range └─ std::runtime_error ├─ std::range_error ├─ std::overflow_error └─ std::underflow_error
std::logic_error
: A programozási logika hibáit reprezentálja, amelyeket általában a kód helytelen felépítése vagy érvelése okoz.std::runtime_error
: Futásidejű hibák, külső környezeti tényezők (pl. fájlkezelés, hálózat) miatt bekövetkező kivételek.
std::exception
és alapvető tulajdonságaiA std::exception
az ős, amely az alábbi virtuális metódust definiálja:
virtual const char* what() const noexcept;
what()
: Visszaad egy human–readable üzenetet a kivételről.noexcept
: Biztosítja, hogy a what()
maga nem fog másik kivételt dobni.Mivel minden szabványos kivétel ebből származik, egy egységes kezelőblokkban is el lehet kapni:
try {
// … kód, ami kivételt dobhat …
} catch (const std::exception& e) {
std::cerr << "Hiba: " << e.what() << '\n';
}
Ez a minta egyszerűsített, de nem tesz különbséget a különböző hibaszituációk között.
<stdexcept>
fejléc osztályai
std::logic_error
és származékaistd::invalid_argument
: Hibás argumentum átadásakor.std::domain_error
: Matematikai függvények érvénytelen tartományában.std::length_error
: Túl nagy hosszúságú adat esetén (például string, konténer).std::out_of_range
: Indexelési hiba, amikor túllépünk egy tartományt.#include <stdexcept>
#include <vector>
int safe_at(const std::vector<int>& v, size_t idx) {
if (idx >= v.size())
throw std::out_of_range("Index túl nagy: " + std::to_string(idx));
return v;
}
std::runtime_error
és származékaistd::range_error
: Numerikus tartománytúllépés.std::overflow_error
: Átfolyás (overflow) esetén.std::underflow_error
: Alulfolyás (underflow) esetén.double reciprocal(double x) {
if (x == 0.0)
throw std::domain_error("Nullával való osztás");
return 1.0 / x;
}
Dobás (throw
)
what()
-ban.Elkapás (catch
)
Specifikus → általános sorrendben:
try {
// ...
} catch (const std::out_of_range& e) {
// Speciális kezelés
} catch (const std::exception& e) {
// Általános kezelés
}
Kerülje a catch(...)
általános fogást, hacsak nem valóban utolsó védvonalról van szó.
Újradobás (rethrow
)
Ha a függvény nem tudja kezelni a kivételt, újra lehet dobni:
catch (const std::exception& e) {
// naplózás
throw; // eredeti kivétel továbbítása
}
Ha a szabványos osztályok nem fedik le a domain-specifikus hibákat, készíthetünk sajátokat:
class FileParseError : public std::runtime_error {
public:
explicit FileParseError(const std::string& filename, int line)
: std::runtime_error("Hiba a fájlban: " + filename +
" sor: " + std::to_string(line)) {}
};
std::runtime_error
-ből vagy std::logic_error
-ből a hiba jellege szerint.
noexcept
).A RAII (Resource Acquisition Is Initialization) minta automatikusan kezeli az erőforrásokat (memória, fájl, mutex), még kivételek esetén is:
std::lock_guard<std::mutex> lock(mutex);
// garantáltan feloldódik a blokkon való kilépéskor
noexcept
és teljesítményA noexcept
kulcsszóval jelezhetjük, hogy egy függvény nem dob kivételt:
void func() noexcept { /* … */ }
noexcept
esetén a fordító optimalizációkat végezhet (pl. move-eléseket), és a Standard Library konténerek is érzékelik, hogy biztonságosan mozgathatják az elemeket.
A move-konstruktorokat és move-operatorokat érdemes noexcept
-ként definiálni, hogy a konténerek hatékonyabban működjenek.
std::exception
–t.int
, char*
), csak osztályokat örökölve.noexcept
mindenhol, ahol lehetséges, a teljesítmény és a biztonság érdekében.
A <stdexcept>
és <exception>
fejléc osztályai egységes, jól átgondolt eszköztárat kínálnak a C++ futásidejű és logikai hibáinak kezelésére. A megfelelő osztályválasztás, a specifikus kivételek használata, a részletes what()
-üzenetek, továbbá a RAII és noexcept
alkalmazása együtt erős, megbízható és karbantartható kódot eredményez. A gyakorlatban érdemes következetesen alkalmazni ezeket a mintákat, dokumentálni a dobható kivétel típusokat, és csak ott fogni el a kivételeket, ahol valóban tudjuk kezelni a hibát. A szabványos kivételek kiegészíthetők domain-specifikus, egyéni osztályokkal, amellyel még inkább szemantikus és karbantartható lesz a kivételkezelésünk.