C++ Exception Handling Beheersen: Een Uitgebreide Gids
Een exception (uitzondering) is een probleem dat ontstaat tijdens de uitvoering van een programma. Een C++ exception is een reactie op een uitzonderlijke omstandigheid die ontstaat tijdens een programma draait, zoals een poging om door nul te delen.
Exceptions bieden een manier om controle over te dragen van een deel van een programma naar een ander. C++ exception handling is gebaseerd op drie trefwoorden: try, catch, en throw.
throw – Een programma gooit een exception wanneer een probleem opduikt. Dit wordt gedaan met het throw trefwoord.
catch – Een programma vangt een exception op met een exception handler op de plek in een programma waar u het probleem wilt afhandelen. Het catch trefwoord duidt het vangen van een exception aan.
try – Een try blok identificeert een blok code waarvoor bepaalde exceptions geactiveerd zullen worden. Het wordt gevolgd door één of meer catch blokken.
Aannemend dat een blok een exception zal opwerpen, vangt een methode een exception op met een combinatie van de try en catch trefwoorden. Een try/catch blok wordt geplaatst rond de code die een exception kan genereren. Code binnen een try/catch blok wordt aangeduid als beschermde code, en de syntax voor het gebruik van try/catch is als volgt:
try {
// beschermde code
} catch( ExceptionName e1 ) {
// catch blok
} catch( ExceptionName e2 ) {
// catch blok
} catch( ExceptionName eN ) {
// catch blok
}
U kunt meerdere catch statements opsommen om verschillende typen exceptions te vangen voor het geval uw try blok meer dan één exception in verschillende situaties opwerpt.
Exceptions Gooien (Throwing Exceptions)
Exceptions kunnen overal binnen een codeblok gegooid worden met een throw statement. De operand van de throw statement bepaalt een type voor de exception en kan elke expressie zijn en het type van het resultaat van de expressie bepaalt het type exception dat gegooid wordt.
Hier volgt een voorbeeld van het gooien van een exception wanneer een deling door nul conditie optreedt:
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
Exceptions Vangen (Catching Exceptions)
Het catch blok na het try blok vangt elke exception op. U kunt specificeren welk type exception u wilt vangen en dit wordt bepaald door de exception declaratie die verschijnt tussen haakjes na het trefwoord catch.
try {
// beschermde code
} catch( ExceptionName e ) {
// code om ExceptionName exception af te handelen
}
Bovenstaande code vangt een exception van ExceptionName type op. Als u wilt specificeren dat een catch blok elk type exception moet afhandelen dat in een try blok gegooid wordt, moet u een ellipsis, ..., tussen de haakjes die de exception declaratie omsluiten plaatsen als volgt:
try {
// beschermde code
} catch(...) {
// code om elke exception af te handelen
}
Het volgende is een voorbeeld, dat een deling door nul exception gooit en we vangen het in het catch blok.
Live Demo #include <iostream>
using namespace std;
double division(int a, int b) {
if( b == 0 ) {
throw "Division by zero condition!";
}
return (a/b);
}
int main () {
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
} catch (const char* msg) {
cerr << msg << endl;
}
return 0;
}
Omdat we een exception van type const char* opwerpen, moeten we const char* in het catch blok gebruiken tijdens het vangen van deze exception. Als we de bovenstaande code compileren en draaien, zou dit het volgende resultaat produceren:
Division by zero condition!
C++ Standaard Exceptions
C++ biedt een lijst van standaard exceptions gedefinieerd in <exception> die we in onze programma's kunnen gebruiken. Deze zijn gerangschikt in een parent-child klasse hiërarchie zoals hieronder getoond:
Hier is de kleine beschrijving van elke exception vermeld in de bovenstaande hiërarchie:
| Nr. | Exception & Beschrijving |
|---|---|
| 1 | std::exception Een exception en parent klasse van alle standaard C++ exceptions. |
| 2 | std::bad_alloc Dit kan gegooid worden door new. |
| 3 | std::bad_cast Dit kan gegooid worden door dynamic_cast. |
| 4 | std::bad_exception Dit is een nuttig hulpmiddel om onverwachte exceptions in een C++ programma af te handelen. |
| 5 | std::bad_typeid Dit kan gegooid worden door typeid. |
| 6 | std::logic_error Een exception die theoretisch gedetecteerd kan worden door de code te lezen. |
| 7 | std::domain_error Dit is een exception gegooid wanneer een wiskundig ongeldig domein gebruikt wordt. |
| 8 | std::invalid_argument Dit wordt gegooid door ongeldige argumenten. |
| 9 | std::length_error Dit wordt gegooid wanneer een te grote std::string gecreëerd wordt. |
| 10 | std::out_of_range Dit kan gegooid worden door de 'at' methode, bijv. een std::vector en std::bitset<>::operator[](). |
| 11 | std::runtime_error Een exception die theoretisch niet gedetecteerd kan worden door de code te lezen. |
| 12 | std::overflow_error Dit wordt gegooid als een wiskundige overflow optreedt. |
| 13 | std::range_error Dit treedt op wanneer u probeert een waarde op te slaan die out of range is. |
| 14 | std::underflow_error Dit wordt gegooid als een wiskundige underflow optreedt. |
Nieuwe Exceptions Definiëren (Define New Exceptions)
U kunt uw eigen exceptions definiëren door exception klasse te overerven en te overriden. Hier volgt het voorbeeld, dat laat zien hoe u std::exception klasse kunt gebruiken om uw eigen exception op standaard manier te implementeren:
Live Demo #include <iostream>
#include <exception>
using namespace std;
struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
int main() {
try {
throw MyException();
} catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
} catch(std::exception& e) {
// Andere fouten
}
}
Dit zou het volgende resultaat produceren:
MyException caught C++ Exception
Hier is what() een publieke methode geleverd door exception klasse en het is geoverride door alle child exception klassen. Dit retourneert de oorzaak van een exception.
C Taal
- C++ operators: complete gids met praktische voorbeelden
- C++ comments: best practices voor leesbare, onderhoudbare code
- C++ Class Templates Beheersen: Een Praktische Gids
- C Bestandsbehandeling: I/O onder de knie krijgen met fopen, fprintf, fread en fseek
- C++ Exception Handling: Praktische Try, Catch, Throw Voorbeelden
- Foutafhandeling in C: Best Practices & Technieken
- C++ Programmeertaal: Overzicht & Belangrijkste Kenmerken
- C++ Constanten & Literals Uitgelegd: Types, Syntax en Best Practices
- Uitgebreide Gids voor C++ Operators: Types, Gebruik en Best Practices
- Python Exception Handling Onder de Loep: try, except, finally en raise Effectief Gebruiken
- Java Exception Handling meesteren: Try, Catch, Finally, Throw & Throws uitgelegd