2010-09-04 18 views
21

मैं एक अपवादसी एक अपवाद पकड़ में पकड़ा (...)

catch(...) 

ब्लॉक द्वारा पकड़ा के विवरण प्राप्त कर सकते हैं ब्लॉक का वर्णन मिलता है ++? कुछ .what() std :: अपवाद।

+1

'की सी ++ 11 rethrowing में std :: current_exception' का उपयोग कैच-ऑल ब्लॉक में अपवाद का 'क्या' संदेश प्राप्त करने के लिए किया जा सकता है: http://stackoverflow.com/a/37222762/5447906 –

उत्तर

38

वहाँ एक चाल आप उपयोग करने में सक्षम हो सकता है:

catch(...) { 
    handle_exception(); 
} 

void handle_exception() { 
    try { 
     throw; 
    } catch (const std::exception &e) { 
     std::cout << e.what() << "\n"; 
    } catch (const int i) { 
     std::cout << i << "\n"; 
    } catch (const long l) { 
     std::cout << l << "\n"; 
    } catch (const char *p) { 
     std::cout << p << "\n"; 
    } catch (...) { 
     std::cout << "nope, sorry, I really have no clue what that is\n"; 
    } 

और इतने पर, के रूप में कई अलग अलग प्रकार के लिए के रूप में आपको लगता है फेंक दिया जा सकता है। यदि आपको वास्तव में कुछ भी नहीं पता कि क्या फेंक दिया जा सकता है, तो दूसरा भी आखिरी वाला गलत है, क्योंकि कोई char* फेंक सकता है जो एक नल-टर्मिनेटेड स्ट्रिंग को इंगित नहीं करता है।

यह आमतौर पर std::exception या व्युत्पन्न कक्षा नहीं है जो कुछ भी फेंकना एक बुरा विचार है। std::exception कारण मौजूद है कि सभी को वस्तुओं को फेंकने और पकड़ने दें ताकि वे कुछ उपयोगी कर सकें। एक खिलौना कार्यक्रम में जहां आप वहां से बाहर निकलना चाहते हैं और मानक हेडर को शामिल करने के लिए भी परेशान नहीं किया जा सकता है, ठीक है, शायद int या स्ट्रिंग अक्षर को फेंक दें। मुझे नहीं लगता कि मैं औपचारिक इंटरफ़ेस का वह हिस्सा बनाउंगा। आपके द्वारा फेंकने वाले किसी भी अपवाद आपके औपचारिक इंटरफेस का हिस्सा हैं, भले ही आप उन्हें दस्तावेज करना भूल गए हों।

+2

हाय; यह एक अच्छा जवाब है। मैं मानकों के दस्तावेजों में साक्ष्य खोजने के लिए कुछ समय ढूंढ रहा हूं कि यह मानक व्यवहार है, लेकिन कोई भी खोजने में असमर्थ रहा है। क्या आप निश्चित रूप से जानते हैं कि यह मानक व्यवहार है? (यानी, 'कैच (...) {} 'के अंदर एक नया' try'-block दर्ज करना और इसके प्रकार को निर्धारित करने के लिए अपवाद को दोबारा डालना।) – NHDaly

+1

स्मृति से कार्य करना: जीवन भर के बारे में पाठ की तलाश करें वर्तमान अपवाद (जब तक आप पकड़ खंड से बाहर नहीं निकलते), और बिना किसी ऑपरेंड के 'थ्रो' का प्रभाव (वर्तमान अपवाद को पुनर्स्थापित करता है)। –

5

वह ब्लॉक एक int, या एक const char *, या कुछ भी पकड़ सकता है। संकलक संभवतः कुछ कैसे वर्णन कर सकता है जब यह इसके बारे में कुछ नहीं जानता? अगर आप अपवाद से जानकारी प्राप्त करना चाहते हैं, तो आपको इस प्रकार का पता होना चाहिए।

+5

"कंपाइलर संभवतः कुछ कैसे वर्णन कर सकता है जब यह जानता है इसके बारे में कुछ नहीं? " - +1, लेकिन असल में, कंपाइलर इसके बारे में कुछ जानता है। अपवाद तंत्र को * कुछ * प्रकार की जानकारी स्टोर करनी चाहिए, क्योंकि इसे कैच क्लॉज के खिलाफ अपवाद ऑब्जेक्ट से मेल खाना पड़ेगा। लेकिन मानक इस जानकारी को परिभाषित नहीं करता है या उस तक पहुंच प्रदान नहीं करता है, यह एक छुपा कार्यान्वयन विस्तार है। –

+0

इस प्रकार की जानकारी कहीं भी इस ऑपरेशन को करने के लिए पर्याप्त नहीं है, और कोई कार्यान्वयन उसमें बदलाव नहीं कर सकता है। – Puppy

+1

एक चुनौती की तरह लगता है ;-) एक कंपाइलर एक्सटेंशन '__what()' जो एक स्ट्रिंग देता है जिसमें वर्तमान अपवाद के टाइपिनोफ़ नाम (कार्यान्वित करने में आसान) होता है, उसके बाद उसके मूल्य का वर्णन करने वाले अधिक वर्ण (अभ्यास में आप आसानी से लेकिन आसानी से कवर कर सकते हैं बिल्टिन प्रकार, और अधिकांश मानक पुस्तकालय, और शायद उपयोगकर्ता परिभाषित प्रकारों के लिए कुछ बुनियादी कार्यान्वयन हैं)। निस्संदेह इसका मतलब यह होगा कि प्रत्येक स्ट्रिंग रूपांतरण करने के लिए प्रत्येक प्रकार के लिए कुछ ब्लॉटी कोड उत्सर्जित करने वाला संकलक होगा, लेकिन फिर सोचें कि कितने 'ऑपरेटर <<' पहले से मौजूद हैं। सबकुछ के लिए यह करना, ज़ाहिर नहीं है। –

4

क्या आप जानते हैं कि आप केवल std :: अपवाद या उपवर्गों फेंक, तो,

catch(std::exception& e) {...e.what()... } 

अन्यथा कोशिश के रूप में DeadMG लिखा था, जब से तुम (लगभग) सब कुछ फेंक कर सकते हैं, आप क्या पकड़ा बारे में कुछ भी कल्पना नहीं कर सकते।

सामान्य रूप से पकड़ (...) बुरी तरह लिखित या दस्तावेजी बाहरी पुस्तकालयों का उपयोग करते समय अंतिम रक्षा के रूप में उपयोग किया जाना चाहिए। तो अगर आप एक पदानुक्रम

catch(my::specialException& e) { 
     // I know what happened and can handle it 
     ... handle special case 
     } 
catch(my::otherSpecialException& e) { 
     // I know what happened and can handle it 
     ... handle other special case 
     } 
catch(std::exception& e) { 
     //I can at least do something with it 
     logger.out(e.what()); 
     } 
catch(...) { 
    // something happened that should not have 
    logger.out("oops"); 
    } 
2

हम अपने अपवादों को लागू किया है का प्रयोग करेंगे कि, हम अपने अपवाद कक्षाएं, कि सभी std::exception से प्राप्त कर रहे ..

हमारे अपवाद अपवाद संदेश में शामिल होंगे है, समारोह है नाम, फ़ाइल का नाम और रेखा जहां अपवाद उत्पन्न होते हैं। ये सभी संदेश दिखाने के लिए उपयोगी नहीं हैं बल्कि लॉगिंग के लिए भी उपयोग किए जा सकते हैं जो अपवाद को आसानी से निदान करने में मदद करता है। इसलिए, हमें उत्पन्न अपवादों के बारे में पूरी जानकारी मिलती है।

याद रखें कि गलत होने के बारे में जानकारी प्राप्त करने के लिए हमें के लिए अपवाद हैं। तो, जानकारी के हर बिट इस संबंध में मदद करता है ..

3

सी ++ 11 के बाद से आप एक सूचक के साथ वर्तमान अपवाद पर कब्जा कर सकते हैं:

std::exception_ptr p;  // default initialization is to nullptr 

try { 
     throw 7; 
} 
catch(...) 
{ 
    p = std::current_exception(); 
} 

यह एक स्मार्ट सूचक की तरह बर्ताव करता; जब तक अपवाद वस्तु को इंगित करने वाले कम से कम एक पॉइंटर होता है तो यह नष्ट नहीं होता है।

बाद में (शायद यह भी एक अलग समारोह में) आप वर्तमान शीर्ष जवाब देने के लिए एक समान तरीके से कार्रवाई कर सकते हैं:

try { 
    if (p) 
     std::rethrow_exception(p); 
} 
catch(int x) 
{ 

} 
catch(std::exception &y) 
{ 
} 
2

का हवाला देते हुए bobah

#include <iostream> 

#include <exception> 
#include <typeinfo> 
#include <stdexcept> 

int main() 
{ 
    try { 
     throw ...; // throw something 
    } 
    catch(...) 
    { 
     std::exception_ptr p = std::current_exception(); 
     std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl; 
    } 
    return 1; 
} 
+1

यह मानक या पोर्टेबल नहीं है। यह * कार्यान्वयन-विशिष्ट विवरण * पर निर्भर करता है जो कि कंपाइलर्स के बीच भिन्न होता है। 'std :: upgrade_ptr' एक * निर्दिष्ट * प्रकार के लिए एक स्मार्ट साझा सूचक है, इसलिए कोई गारंटी नहीं है कि' __cxa_exception_type() 'मौजूद है –

संबंधित मुद्दे