logo

Poikkeuskäsittely C++:ssa

C++:ssa poikkeukset ovat ajonaikaisia ​​poikkeavuuksia tai epänormaaleja olosuhteita, joita ohjelma kohtaa suorituksensa aikana. Näiden poikkeusten käsittelyprosessia kutsutaan poikkeuskäsittelyksi. Poikkeuskäsittelymekanismin avulla ohjaus ohjelman yhdestä osasta, jossa poikkeus tapahtui, voidaan siirtää toiseen koodin osaan.

Joten pohjimmiltaan käyttämällä poikkeusten käsittelyä C++:ssa, voimme käsitellä poikkeuksia niin, että ohjelmamme jatkaa toimintaansa.



1 miljoona kuinka monta 0

Mikä on C++-poikkeus?

Poikkeuksena on odottamaton ongelma, joka ilmenee ohjelman suorituksen aikana ja ohjelmamme päättyy äkillisesti virheiden/ongelmien vuoksi. Poikkeus tapahtuu ohjelman ajon aikana (ajoaika).

C++-poikkeuksen tyypit

C++:ssa on kahdenlaisia ​​poikkeuksia

  1. Synkroninen: Poikkeuksia, joita tapahtuu, kun jokin menee pieleen syötetietojen virheen vuoksi tai kun ohjelma ei ole varustettu käsittelemään senhetkistä datatyyppiä, kuten jakamalla luku nollalla.
  2. Asynkroninen : Poikkeukset, jotka eivät ole ohjelman hallinnassa, kuten levyvika, näppäimistön keskeytykset jne.

C++ kokeile kiinni

C++ tarjoaa sisäänrakennetun ominaisuuden poikkeusten käsittelyyn. Se voidaan tehdä käyttämällä seuraavia erityisiä avainsanoja: yritä, saa kiinni ja heittää, joilla kullakin on eri tarkoitus.



Try-catchin syntaksi C++:ssa

  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. Kokeile C++:ssa

Try-avainsana edustaa koodilohkoa, joka voi heittää try-lohkon sisään sijoitetun poikkeuksen. Sitä seuraa yksi tai useampi kiinnityslohko. Jos tapahtuu poikkeus, yritä estää poikkeuksen heitto.

2. saalis C++:ssa

Catch-lause edustaa koodilohkoa, joka suoritetaan, kun tietty poikkeus heitetään try-lohkosta. Poikkeuksen käsittelykoodi on kirjoitettu catch-lohkon sisään.

3. kirjoita C++

Poikkeus C++:ssa voidaan heittää käyttämällä throw-avainsanaa. Kun ohjelma kohtaa heittokäskyn, se lopettaa välittömästi nykyisen funktion ja alkaa etsiä vastaavaa catch-lohkoa käsitelläkseen heitetyn poikkeuksen.



Huomautus: Useita catch-lauseita voidaan käyttää erityyppisten try-lohkon heittämien poikkeuksien havaitsemiseen.

Try and catch -avainsanat tulevat pareittain: Käytämme try-lohkoa jonkin koodin testaamiseen ja jos koodi heittää poikkeuksen, käsittelemme sen catch-lohkossamme.

Miksi tarvitsemme Poikkeuskäsittely C++:ssa?

Seuraavat ovat poikkeusten käsittelyn tärkeimmät edut perinteiseen virheenkäsittelyyn verrattuna:

  1. Virheenkäsittelykoodin erottaminen normaalista koodista : Perinteisissä virheenkäsittelykoodeissa on aina jos-else-ehtoja virheiden käsittelemiseksi. Nämä ehdot ja virheiden käsittelykoodi sekoittuvat normaaliin virtaukseen. Tämä tekee koodista vähemmän luettavan ja ylläpidettävän. Try/catch-lohkoilla virheenkäsittelyn koodi erottuu normaalista kulusta.
  2. Funktiot/menetelmät voivat käsitellä vain valitsemiaan poikkeuksia : Funktio voi tehdä monia poikkeuksia, mutta voi päättää käsitellä joitakin niistä. Muut poikkeukset, jotka heitetään, mutta eivät jää kiinni, voidaan soittaja hoitaa. Jos soittaja päättää olla tavoittamatta heitä, soittajan soittaja hoitaa poikkeukset.
    C++:ssa funktio voi määrittää poikkeukset, jotka se heittää käyttämällä throw-avainsanaa. Tämän funktion kutsujan on käsiteltävä poikkeus jollakin tavalla (joko määrittämällä se uudelleen tai saamalla se kiinni).
  3. Virhetyyppien ryhmittely : C++:ssa sekä perustyypit että objektit voidaan heittää poikkeuksina. Voimme luoda poikkeusobjektien hierarkian, ryhmitellä poikkeuksia nimiavaruuksiin tai luokkiin ja luokitella ne tyyppien mukaan.

Esimerkkejä poikkeusten käsittelystä C++:ssa

Seuraavat esimerkit osoittavat, kuinka try-catch-lohkoa käytetään poikkeuksien käsittelemiseen C++:ssa.

Esimerkki 1

Alla oleva esimerkki havainnollistaa heittopoikkeuksia C++:ssa.

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;> }>

>

>

Lähtö

Exception Division by zero not allowed!>

Esimerkki 2

Seuraava on yksinkertainen esimerkki poikkeuksien käsittelystä C++:ssa. Ohjelman tulos selittää try/catch-lohkojen suoritusvirran.

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;> }>

>

>

Lähtö

Before try Inside try Exception Caught After catch (Will be executed)>

Poikkeuskäsittelyn ominaisuudet C++:ssa

Kiinteistö 1

On olemassa erityinen catch-all-lohko, jota kutsutaan 'catch-all'-lohkoksi, joka on kirjoitettu nimellä catch(…), jota voidaan käyttää kaikentyyppisten poikkeuksien sieppaamiseen.

Esimerkki

Seuraavassa ohjelmassa int heitetään poikkeuksena, mutta int:lle ei ole catch-lohkoa, joten catch(…)-lohko suoritetaan.

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;> }>

>

>

Lähtö

Default Exception>

Kiinteistö 2

Implisiittistä tyyppimuunnosa ei tapahdu primitiivisille tyypeille.

susi vs kettu

Esimerkki

Seuraavassa ohjelmassa 'a' ei ole implisiittisesti muunnettu int.

CPP




css-siirtymän läpinäkyvyys
//// 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;> }>

>

>

Lähtö

Default Exception>

Lähtö:

Default Exception>

Kiinteistö 3

Jos poikkeus heitetään eikä sitä saada kiinni minnekään, ohjelma päättyy epänormaalisti.

Esimerkki

Seuraavassa ohjelmassa char heitetään, mutta ei ole mitään pyydystyslohkoa nikeron kiinni saamiseksi.

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;> }>

>

>

Lähtö

terminate called after throwing an instance of 'char'>

Voimme muuttaa tätä epänormaalia lopetuskäyttäytymistä kirjoittamalla odottamattoman funktiomme.

Huomautus : Johdettu luokkapoikkeus tulee kiinnittää ennen perusluokan poikkeusta.

Kuten Java, C++-kirjastossa on a tavallinen poikkeus luokka, joka on perusluokka kaikille vakiopoikkeuksille. Kaikki vakiokirjaston komponenttien heittämät objektit on johdettu tästä luokasta. Siksi kaikki tavalliset poikkeukset voidaan saada kiinni tämän tyypin pyydystämisellä.

Kiinteistö 4

Toisin kuin Java, C++:ssa kaikkia poikkeuksia ei ole valittu, eli kääntäjä ei tarkista, onko poikkeus kiinni vai ei (katso Tämä yksityiskohtia varten). Joten ei ole tarpeen määrittää kaikkia tavoittamattomia poikkeuksia funktion määrittelyssä. Poikkeuskäsittely on kuitenkin suositeltava käytäntö.

Esimerkki

Seuraava ohjelma kääntää hyvin, mutta ihannetapauksessa fun():n allekirjoituksen pitäisi luetella valitsemattomat poikkeukset.

CPP




// 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;> }>

>

>

Lähtö

Caught exception from fun()>

Parempi tapa kirjoittaa yllä oleva koodi:

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;> }>

>

valinta lajittelu

>

Lähtö

Caught exception from fun()>

Huomautus : Dynaamisen poikkeusmäärityksen käyttö on poistettu käytöstä C++11:n jälkeen. Yksi syy siihen voi olla se, että se voi keskeyttää ohjelman satunnaisesti. Tämä voi tapahtua, kun teet toisen tyyppisen poikkeuksen, jota ei mainita dynaamisissa poikkeuksissa. Ohjelmasi keskeyttää itsensä, koska siinä skenaariossa se kutsuu (epäsuorasti) terminate(), joka oletusarvoisesti kutsuu abort().

Kiinteistö 5

C++:ssa try/catch-lohkot voivat olla sisäkkäisiä. Poikkeus voidaan myös heittää uudelleen heittämällä; .

Esimerkki

Seuraava ohjelma näyttää try/catch-lohkot sisäkkäin.

CPP




// 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;> }>

>

>

Lähtö

Handle Partially Handle remaining>

Funktio voi myös heittää funktion uudelleen käyttämällä samaa heittoa; syntaksi. Toiminto voi käsitellä osan ja pyytää soittajaa käsittelemään loput.

Kiinteistö 6

Kun poikkeus heitetään, kaikki sulkevan try-lohkon sisällä luodut objektit tuhoutuvat ennen kuin ohjaus siirretään catch-lohkoon.

Esimerkki

Seuraava ohjelma esittelee yllä olevan ominaisuuden.

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;> >}> }>

>

>

Lähtö

Constructor of Test Destructor of Test Caught 10>

Poikkeuskäsittelyn rajoitukset C++:ssa

Poikkeuskäsittelyllä C++:ssa on myös muutamia rajoituksia:

lateksi tekstin koot
  • Poikkeukset voivat rikkoa koodin rakenteen tai kulun, koska koodiin luodaan useita näkymättömiä poistumispisteitä, mikä tekee koodista vaikeasti luettavan ja virheenkorjauksen.
  • Jos poikkeusten käsittelyä ei tehdä kunnolla, se voi johtaa myös resurssivuotoon.
  • On vaikea oppia kirjoittamaan turvallista poikkeuskoodia.
  • Poikkeuskäsittelyn käytölle ei ole olemassa C++-standardia, joten poikkeusten käsittelykäytännöissä on monia muunnelmia.

Johtopäätös

Poikkeuskäsittelyä C++:ssa käytetään odottamattomien tapahtumien käsittelemiseen käyttämällä try and catch -lohkoja ongelman tehokkaaseen hallintaan. Tämä poikkeuskäsittely tekee ohjelmistamme luotettavampia, koska ajonaikaiset virheet voidaan käsitellä erikseen ja se auttaa myös estämään ohjelman kaatumisen ja ohjelman äkillisen lopettamisen, kun virhe havaitaan.

Aiheeseen liittyvät artikkelit:

  • Parhaat C++-poikkeuksien käsittelyn haastattelukysymykset ja vastaukset
  • Tietokilpailu poikkeusten käsittelystä C++:ssa