2016-09-11 2 views
5

Betrachten Sie diesen Code:Ausnahme Auffangmechanismus, C++

int main() 
{ 
    try 
    { 
     throw std::range_error(""); 
    } 
    catch (std::bad_alloc) 
    { 
     std::cout << "AAAA" << std::endl; 
     throw; 
    } 
    catch (std::range_error) 
    { 
     std::cout << "BBB" << std::endl; 
     throw; 
    } 
    catch (std::exception) 
    { 
     std::cout << "CCC" << std::endl; 
    } 
    std::cout << "DDD" << std::endl; 
} 

Hier werfe ich eine Ausnahme vom Typ std::range_error und versuchen, sie zu fangen.
Logisch der erste catch Block kann es nicht fangen wegen Typ Mismatch (std::bad_alloc und std::range_error).
Der zweite Fangblock muss ihn fangen, da es sich um die gleichen Typen von std::range_error handelt.
Und auch, wenn ich die Ausnahme im zweiten catch-Block erneut auslösen, muss es im dritten catch-Block gefangen werden.

So muss meine Ausgabe

BBB 
CCC 
DDD 

sein, aber ich nur den BBB Ausgang mit der Beendigung erhalten.

Kann mir bitte jemand das Verhalten erklären ??

+2

Ihr zweiter Wurf nicht in einem 'try' Block auftritt. So kann es nicht gefangen werden. – Galik

+2

Es funktioniert nicht so.Jeder try-catch-Block erhält nur einen Schuss bei der Ausnahme, egal wie viele Fangklauseln es gibt. Ausnahmen, die von einer catch-Klausel ausgelöst werden, werden in diesem try-catch-Block nicht abgefangen. – davidbak

+0

Das bedeutet, dass selbst wenn ich viele Catch-Blöcke vom Ausnahmetyp habe, nur der erste die Ausnahme fängt, bin ich richtig? –

Antwort

6

Wenn Sie throw eine Ausnahme re-, werden Sie es vollständig aus dem Kontext des aktuellen Ausnahmebehandlungsblock zu werfen .... also,

try 
{ 
    throw std::range_error(""); 
} 
catch (std::bad_alloc) 
{ 
    std::cout << "AAAA" << std::endl; 
    throw; 
} 
catch (std::range_error) 
{ 
    std::cout << "BBB" << std::endl; 
    throw; 
} 
catch (std::exception) 
{ 
    std::cout << "CCC" << std::endl; 
} 

ist ein Exception Handling Block. Wenn der erste throw in einem der catch Blöcke erfüllt wird, verlässt es daher den gesamten Block, um nach einem anderen Bearbeitungsblock (try-catch) außerhalb des aktuellen Bereichs zu suchen. Wenn nicht gefunden, wird das Programm beendet.

Bitte sehen try-catch block in C++

als Sie ursprünglich gedacht drucken ... Live On Coliru ...

int main() 
{ 
    try{ 
     try{ 
      try{ 
       throw std::range_error(""); 
      } 
      catch (std::bad_alloc) { 
       std::cout << "AAAA" << std::endl; 
       throw; 
      } 
     } 
     catch (std::range_error) { 
      std::cout << "BBB" << std::endl; 
      throw; 
     } 
    } 
    catch (std::exception){ 
     std::cout << "CCC" << std::endl; 
    } 
    std::cout << "DDD" << std::endl; 
} 

Drucke:

BBB 
CCC 
DDD 

Für das Protokoll: vermeiden Sie Ausnahmen für die Steuerung mit Fluss, der mit einfachen if-else Leiter in Produktionscode

getan werden konnte
4

Diese throw:

catch (std::range_error) 
{ 
    std::cout << "BBB" << std::endl; 
    throw; // <== this one 
} 

nicht selbst im Körper eines try, so dass, wenn die Ausnahmebehandlung halten zu einem Zeitpunkt ein Rahmen gehen, bis es eine findet. Da es keine anderen äußeren try gibt, wird die Ausnahme überhaupt nicht gefangen.

Es gibt kein Wiedereintreten in der Ausnahmebehandlung.

5

Um den range_error erneut zu fangen, ist ein neuer externer try catch-Block erforderlich.

#include <iostream> 

int main() 
{ 
    //outer try catch ------------------------ 
    try { 

    // inner try catch --------------------- 
    try 
    { 
     throw std::range_error(""); 
    } 
    catch (std::bad_alloc) 
    { 
     std::cout << "AAAA" << std::endl; 
     throw; 
    } 
    catch (std::range_error) 
    { 
     std::cout << "BBB" << std::endl; 
     throw; 
    } 
    // ------------------------------- 
    } 

    catch (std::exception) 
    { 
    std::cout << "CCC" << std::endl; 
    } 
    // -------------------------------- 

    std::cout << "DDD" << std::endl; 
} 

Ausgabe

BBB 
CCC 
DDD