In C++ zijn uitzonderingen runtime-afwijkingen of abnormale omstandigheden die een programma tegenkomt tijdens de uitvoering ervan. Het proces voor het afhandelen van deze uitzonderingen wordt uitzonderingsafhandeling genoemd. Met behulp van het uitzonderingsverwerkingsmechanisme kan de besturing van een deel van het programma waar de uitzondering plaatsvond, worden overgedragen naar een ander deel van de code.
Dus door gebruik te maken van uitzonderingsafhandeling in C++ kunnen we de uitzonderingen afhandelen, zodat ons programma blijft draaien.
geheel getal naar string in Java
Wat is een C++-uitzondering?
Een uitzondering is een onverwacht probleem dat zich voordoet tijdens de uitvoering van een programma. Ons programma wordt plotseling beëindigd met enkele fouten/problemen. Uitzondering treedt op tijdens het uitvoeren van het programma (runtime).
Soorten C++-uitzonderingen
Er zijn twee soorten uitzonderingen in C++
- Synchronisch: Uitzonderingen die optreden wanneer er iets misgaat vanwege een fout in de invoergegevens of wanneer het programma niet is uitgerust om het huidige type gegevens te verwerken waarmee het werkt, zoals het delen van een getal door nul.
- Asynchroon : Uitzonderingen die buiten de controle van het programma liggen, zoals schijfstoringen, toetsenbordonderbrekingen, enz.
C++ proberen en vangen
C++ biedt een ingebouwde functie voor het afhandelen van uitzonderingen. Dit kan worden gedaan met behulp van de volgende gespecialiseerde trefwoorden: proberen, vangen en gooien, waarbij elk een ander doel heeft.
Syntaxis van try-catch in C++
try { // Code that might throw an exception throw SomeExceptionType('Error message'); } catch ( ExceptionName e1 ) { // catch block catches the exception that is thrown from try block }> 1. probeer het in C++
Het try-trefwoord vertegenwoordigt een codeblok dat een uitzondering kan genereren die in het try-blok is geplaatst. Het wordt gevolgd door een of meer catch-blokken. Als er een uitzondering optreedt, probeer dan de uitzondering te blokkeren.
2. vangen in C++
De catch-instructie vertegenwoordigt een codeblok dat wordt uitgevoerd wanneer een bepaalde uitzondering uit het try-blok wordt gegenereerd. De code om de uitzondering af te handelen, wordt in het catch-blok geschreven.
3. gooi C++ erin
Een uitzondering in C++ kan worden gegenereerd met behulp van het trefwoord throw. Wanneer een programma een throw-instructie tegenkomt, beëindigt het onmiddellijk de huidige functie en begint het een passend catch-blok te zoeken om de gegenereerde uitzondering af te handelen.
Opmerking: Er kunnen meerdere catch-instructies worden gebruikt om verschillende soorten uitzonderingen op te vangen die door het try-blok worden gegenereerd.
De try- en catch-sleutelwoorden komen in paren: we gebruiken het try-blok om code te testen en als de code een uitzondering genereert, verwerken we deze in ons catch-blok.
Waarom hebben we nodig Afhandeling van uitzonderingen in C++?
Hieronder volgen de belangrijkste voordelen van uitzonderingsafhandeling ten opzichte van traditionele foutafhandeling:
- Scheiding van foutafhandelingscode van normale code : Er zijn altijd if-else voorwaarden om fouten in traditionele foutafhandelingscodes af te handelen. Deze omstandigheden en de code om fouten af te handelen raken in de war met de normale stroom. Dit maakt de code minder leesbaar en onderhoudbaar. Met try/catch-blokken wordt de code voor foutafhandeling gescheiden van de normale stroom.
- Functies/methoden kunnen alleen de uitzonderingen verwerken die zij kiezen : Een functie kan veel uitzonderingen genereren, maar kan ervoor kiezen om er enkele af te handelen. De andere uitzonderingen, die worden gegooid maar niet worden opgevangen, kunnen door de beller worden afgehandeld. Als de beller ervoor kiest om ze niet op te vangen, worden de uitzonderingen afgehandeld door de beller van de beller.
In C++ kan een functie de uitzonderingen specificeren die worden gegenereerd met behulp van het trefwoord throw. De aanroeper van deze functie moet de uitzondering op een of andere manier afhandelen (door deze opnieuw op te geven of door deze op te vangen).
- Groepering van fouttypen : In C++ kunnen zowel basistypen als objecten als uitzonderingen worden gegenereerd. We kunnen een hiërarchie van uitzonderingsobjecten maken, uitzonderingen groeperen in naamruimten of klassen, en ze categoriseren op basis van hun typen.
Voorbeelden van uitzonderingsafhandeling in C++
De volgende voorbeelden laten zien hoe u een try-catch-blok kunt gebruiken om uitzonderingen in C++ af te handelen.
voorbeeld 1
Het onderstaande voorbeeld demonstreert throw-uitzonderingen in C++.
C++
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >int> numerator = 10;> >int> denominator = 0;> >int> res;> >// check if denominator is 0 then throw runtime> >// error.> >if> (denominator == 0) {> >throw> runtime_error(> >'Division by zero not allowed!'>);> >}> >// calculate result if no exception occurs> >res = numerator / denominator;> >//[printing result after division> >cout <<>'Result after division: '> << res << endl;> >}> >// catch block to catch the thrown exception> >catch> (>const> exception& e) {> >// print the exception> >cout <<>'Exception '> << e.what() << endl;> >}> >return> 0;> }> |
>
>Uitvoer
Exception Division by zero not allowed!>
Voorbeeld 2
Het volgende is een eenvoudig voorbeeld om de afhandeling van uitzonderingen in C++ te tonen. De uitvoer van het programma legt de uitvoeringsstroom van try/catch-blokken uit.
CPP
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> using> namespace> std;> int> main()> {> >int> x = -1;> >// Some code> >cout <<>'Before try
'>;> >// try block> >try> {> >cout <<>'Inside try
'>;> >if> (x <0) {> >// throwing an exception> >throw> x;> >cout <<>'After throw (Never executed)
'>;> >}> >}> >// catch block> >catch> (>int> x) {> >cout <<>'Exception Caught
'>;> >}> >cout <<>'After catch (Will be executed)
'>;> >return> 0;> }> |
>
>Uitvoer
Before try Inside try Exception Caught After catch (Will be executed)>
Eigenschappen van uitzonderingsafhandeling in C++
Eigendom 1
Er is een speciaal catch-blok genaamd het ‘catch-all’-blok, geschreven als catch(…), dat kan worden gebruikt om alle soorten uitzonderingen op te vangen.
Voorbeeld
In het volgende programma wordt als uitzondering een int gegenereerd, maar er is geen catch-blok voor int, dus het catch(…)-blok zal worden uitgevoerd.
CPP
// C++ program to demonstate the use of catch all> // in exception handling.> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >// throw> >throw> 10;> >}> >// catch block> >catch> (>char>* excp) {> >cout <<>'Caught '> << excp;> >}> >// catch all> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
>
>Uitvoer
Default Exception>
Eigenschap 2
Impliciete typeconversie vindt niet plaats voor primitieve typen.
Voorbeeld
In het volgende programma wordt ‘a’ niet impliciet omgezet in int.
rij en kolom
CPP
//// C++ program to demonstate property 2: Implicit type> /// conversion doesn't happen for primitive types.> // in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '> << x;> >}> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
Java-tekenreeks vervangen
>
>Uitvoer
Default Exception>
Uitgang:
Default Exception>
Eigendom 3
Als er een uitzondering optreedt en deze nergens wordt opgevangen, wordt het programma abnormaal beëindigd.
Voorbeeld
In het volgende programma wordt een char gegooid, maar er is geen catch-blok om de char te vangen.
CPP
// C++ program to demonstate property 3: If an exception is> // thrown and not caught anywhere, the program terminates> // abnormally in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '>;> >}> >return> 0;> }> |
>
>
Uitvoer
terminate called after throwing an instance of 'char'>
We kunnen dit abnormale beëindigingsgedrag veranderen door onze onverwachte functie te schrijven.
Opmerking : Een afgeleide klasse-uitzondering moet worden opgevangen vóór een basisklasse-uitzondering.
Net als Java heeft de C++-bibliotheek een standaard uitzondering klasse die de basisklasse is voor alle standaarduitzonderingen. Alle objecten die door de componenten van de standaardbibliotheek worden gegenereerd, zijn afgeleid van deze klasse. Daarom kunnen alle standaarduitzonderingen worden onderschept door dit type op te vangen.
Eigenschap 4
In tegenstelling tot Java zijn in C++ alle uitzonderingen uitgeschakeld, dat wil zeggen dat de compiler niet controleert of een uitzondering wordt opgevangen of niet (zie dit voor details). Het is dus niet nodig om alle niet-afgevangen uitzonderingen in een functiedeclaratie op te geven. Bij het afhandelen van uitzonderingen wordt dit echter aanbevolen.
Voorbeeld
Het volgende programma compileert prima, maar idealiter zou de handtekening van fun() de niet-gecontroleerde uitzonderingen moeten vermelden.
CPP
afdrukken vanuit java
// C++ program to demonstate property 4 in exception> // handling.> #include> using> namespace> std;> // This function signature is fine by the compiler, but not> // recommended. Ideally, the function should specify all> // uncaught exceptions and function signature should be> // 'void fun(int *ptr, int x) throw (int *, int)'> void> fun(>int>* ptr,>int> x)> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Uitvoer
Caught exception from fun()>
Een betere manier om de bovenstaande code te schrijven:
CPP
// C++ program to demonstate property 4 in better way> #include> using> namespace> std;> // Here we specify the exceptions that this function> // throws.> void> fun(>int>* ptr,>int> x)>throw>(> >int>*,>int>)>// Dynamic Exception specification> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Uitvoer
Caught exception from fun()>
Opmerking : Het gebruik van Dynamic Exception Specification is verouderd sinds C++11. Een van de redenen hiervoor kan zijn dat het uw programma willekeurig kan afbreken. Dit kan gebeuren wanneer u een uitzondering genereert van een ander type dat niet wordt vermeld in de dynamische uitzonderingsspecificatie. Uw programma zal zichzelf afbreken omdat het in dat scenario (indirect) termin() aanroept, wat standaard abort() aanroept.
Eigenschap 5
In C++ kunnen try/catch-blokken worden genest. Een uitzondering kan ook opnieuw worden gegooid met behulp van een worp; .
Voorbeeld
Het volgende programma toont het nesten van try/catch-blokken.
CPP
anders als Java
// C++ program to demonstrate try/catch blocks can be nested> // in C++> #include> using> namespace> std;> int> main()> {> >// nesting of try/catch> >try> {> >try> {> >throw> 20;> >}> >catch> (>int> n) {> >cout <<>'Handle Partially '>;> >throw>;>// Re-throwing an exception> >}> >}> >catch> (>int> n) {> >cout <<>'Handle remaining '>;> >}> >return> 0;> }> |
>
>Uitvoer
Handle Partially Handle remaining>
Een functie kan een functie ook opnieuw gooien met dezelfde worp; syntaxis. Een functie kan een deel afhandelen en de beller vragen het resterende deel af te handelen.
Eigenschap 6
Wanneer er een uitzondering wordt gegenereerd, worden alle objecten die binnen het omringende try-blok zijn gemaakt, vernietigd voordat de besturing wordt overgedragen naar het catch-blok.
Voorbeeld
Het volgende programma demonstreert de bovenstaande eigenschap.
CPP
// C++ program to demonstrate> #include> using> namespace> std;> // Define a class named Test> class> Test {> public>:> >// Constructor of Test> >Test() { cout <<>'Constructor of Test '> << endl; }> >// Destructor of Test> >~Test() { cout <<>'Destructor of Test '> << endl; }> };> int> main()> {> >try> {> >// Create an object of class Test> >Test t1;> >// Throw an integer exception with value 10> >throw> 10;> >}> >catch> (>int> i) {> >// Catch and handle the integer exception> >cout <<>'Caught '> << i << endl;> >}> }> |
>
>Uitvoer
Constructor of Test Destructor of Test Caught 10>
Beperkingen van de afhandeling van uitzonderingen in C++
De afhandeling van uitzonderingen in C++ heeft ook enkele beperkingen:
- Uitzonderingen kunnen de structuur of de stroom van de code verstoren, omdat er meerdere onzichtbare uitgangspunten in de code worden gecreëerd, waardoor de code moeilijk te lezen en te debuggen is.
- Als de afhandeling van uitzonderingen niet goed wordt uitgevoerd, kan dit ook leiden tot het lekken van bronnen.
- Het is moeilijk om te leren hoe u uitzonderingscode schrijft die veilig is.
- Er bestaat geen C++-standaard voor het gebruik van uitzonderingsafhandeling. Daarom bestaan er veel variaties in de afhandeling van uitzonderingen.
Conclusie
Uitzonderingsafhandeling in C++ wordt gebruikt om onverwachte gebeurtenissen af te handelen met behulp van try-and-catch-blokken om het probleem efficiënt te beheren. Deze afhandeling van uitzonderingen maakt onze programma's betrouwbaarder omdat fouten tijdens runtime afzonderlijk kunnen worden afgehandeld en het helpt ook voorkomen dat het programma crasht en het programma abrupt wordt beëindigd wanneer er een fout wordt aangetroffen.
Gerelateerde artikelen:
- Top C++ uitzonderingsafhandeling sollicitatievragen en antwoorden
- Quiz over de afhandeling van uitzonderingen in C++