2012-01-23 27 views
10

içine bir şey atmaya çalışırsam sonlandırmaya neden olur. Aşağıdaki C++ kodum var ve bana bir sürpriz veriyor. Sorun şu ki, catch bloğu içinde yeniden fırlatma dışında bir şey atıyorsa, programın iptal edilmesi ve GCC4, "int" örneğini attıktan sonra çağrılan sonlandırmada hata iletisini vermesiyle sonlandırılacaktır. Sadece "atmak" kullanırsam catch bloğunun içine yeniden atmak için her şey iyi olacak.neden bir yakalama bloğu içinde C++

#include <iostream> 
#include <exception> 
#include <stdexcept> 

using namespace std; 

int main() 
{ 
    try{ 
     throw std::string("first throw"); 
    } 
    catch(std::string &x){ 
     try{ 
      std::cout << x << std::endl; 
//   throw; // if I use this line, all is fine. 
      throw int(2); // but if I use this line, it causes Abort() to be called 
     } 
     catch (int &k){ 
      throw; 
     } 
     catch(...) 
     { 
      cout << "all handled here!"<< endl; 
     } 
    } 
    catch(...){ 
     std::cout<< "never printed" << endl; 
    } 
} 
+0

Bir mandaldan fırlatırsanız, bu beklenen bir şeydir. – AJG85

cevap

7

Sen throw böylece çağrıldığını abort sonuçlanan her try işleyicisi içinde değildir. İşte

girinti ile kodunuzu biraz ve bazı yorumlar inline temizlenir: Bir int atarsan

#include <iostream> 
#include <exception> 
#include <stdexcept> 

using namespace std; 

int main() 
{ 
    try { 
     throw std::string("first throw"); 
    } 
    catch (std::string &x) { 
     try { 
      std::cout << x << std::endl; 
      // throw; // if I use this line, all is fine. 
      throw int(2); // but if I use this line, it causes Abort() to be called 
     } 
     catch (int &k) { 
      // Catches and rethrows exception. Not inside a try thus leads to abort. 
      throw; 
     } 
     catch (...) { 
      // Will handle the case where the string is rethrown instead. No abort. 
      cout << "all handled here!"<< endl; 
     } 
    } 
    catch (...) { 
     std::cout<< "never printed" << endl; 
    } 
} 
+0

Teşekkürler, Martin. Yorumlarınız okuyuculara daha açık! –

13

, o zaman ele olmayacak; catch (int &k) işleyici tarafından yakalanacaktır; ve zaten bir dış catch blokta olduğunuz için, yeniden tasarlanmış istisnayı yakalamak için bir dış işleyici yoktur. Bu durumda, işlenmeyen bir özel durum nedeniyle terminate çağrılır.

string'u yeniden kullanırsanız, iç catch(...) işleyicisi tarafından yakalanır; Bu yeniden değil, bu yüzden istisna daha sonra ele alındı.

+0

Teşekkürler, Mike. Cevabın özlü ve doğru olduğunu düşünüyorum. –

+0

Yay/dize atmak için önerilen uygulama mı? –

+0

@StephaneRolland: Genellikle, hayır; hataları veya yerel olarak ele alınamayan diğer koşulları bildirmek için, özel bir tür, genellikle std :: exception'un bir alt sınıfını yazın; ve diğer amaçlarla muhtemelen ilk etapta istisnaları kullanmak istemezsiniz. Ancak istisnaların nasıl çalıştığını öğrenmek için, 'string' ve 'int' her şey kadar iyidir. –