2012-07-02 38 views
5

this site के अनुसार यह एक स्ट्रिंग या पूर्णांक फेंकने के लिए पूरी तरह प्रयोग करने योग्य है। मुझे यह बहुत साफ और समझने में आसान लगता है। के बजाय throw "description of what happened" पर डाउनसाइड्स क्या हैं?सी ++ अपवाद: std :: अपवाद का उपयोग या विस्तार क्यों करें?

उत्तर

13

वह साइट बेवकूफ है, और खराब डिजाइन सिखाती है।

आप int या char* फेंक, तो आप int या char* केवल का उपयोग कर इसे पकड़ने के लिए होगा। आप इसे const के साथ अर्हता प्राप्त कर सकते हैं।

यदि आप std::runtime_error फेंकते हैं, तो आप std::runtime_error const & या इसकी बेस क्लास std::exception const & का उपयोग कर इसे पकड़ सकते हैं।

तो इसके बारे में क्या अच्छा है?

इसके बारे में अच्छा है कि अगर आप एक अपवाद एक वर्ग जो अंततः std::exception से प्राप्त होता है का उपयोग कर फेंक, तो आप सिर्फ एक catch ब्लॉक जो std::exception const& के रूप में अपवाद स्वीकार करता है, which derived class पर ध्यान दिए बिना अपवाद फेंकने के लिए प्रयोग किया जाता है लिख सकते हैं।

void f(A & a) 
{ 
    if (!check_arg(a)) 
    { 
      throw std::invalid_argument("invalid argument"); 
    } 
    else if (!check_size(a)) 
    { 
      throw std::length_error("invalid length");    
    } 

    //code 
    if(someCondition) 
    { 
      //assume your_own_defined_exception's ultimate base is std::exception 
      throw your_own_defined_exception("condition unsatisfied");       
    } 
    //... 

} 

अब दिलचस्प हिस्सा:

यहाँ एक उदाहरण है

try 
{ 
     f(a); //it can throw exception of at least 3 types! 
} 
catch(std::exception const &e) //all types can be caught by just one catch! 
{ 
    //handle this case 
} 

अच्छी बात है कि आप नहीं कर रहे आवश्यकतीनcatch ब्लॉक लिखने के लिए सिर्फ इसलिए f() फेंक सकता है तीन विभिन्न प्रकार के अपवाद। आप एक से अधिक catch लिख सकते हैं ताकि उन्हें अलग-अलग तरीके से संभाला जा सके। लेकिन यहां ध्यान दिया जाने वाला बिंदु यह है: एक आवश्यकता नहीं है!

संक्षेप में, आप कक्षा पदानुक्रम का लाभ उठा सकते हैं।

+0

तो मूल रूप से यह स्वाभाविक रूप से विरासत को त्रुटि प्रबंधन के डिजाइन को सरल बनाने की अनुमति देता है। काफी सुरुचिपूर्ण अगर मैं अपनी अपवाद कक्षा को परिभाषित करता हूं और ऐसा करता हूं, तो मैं वही परिणाम उत्पन्न कर सकता हूं, हां? –

+3

@StevenLu यदि आप अपनी अपवाद कक्षा प्राप्त करते हैं, तो आप पहिया को फिर से शुरू करते हैं, और संभावित रूप से कोड तोड़ते हैं जो std :: अपवाद को पकड़ने पर निर्भर करता है। हालांकि यह आपकी व्यक्तिगत परियोजनाओं के लिए ठीक हो सकता है, यह आपके कोड को दूसरों को वितरित करने में कठोर बनाता है। मानक दृष्टिकोण एक अनुप्रयोग-विशिष्ट अपवाद पदानुक्रम है जो 'std :: अपवाद 'subclasses है। उदाहरण के लिए, आपके सभी अपवाद 'स्टीवन लूएक्सप्शन' के उप-वर्ग हैं, जो 'std :: अपवाद' का उप-वर्ग है। – sfstewman

+0

@StevenLu: यदि आपकी अपवाद वर्ग अंततः 'std :: अपवाद 'से प्राप्त होती है, तो हाँ यह एक सुरुचिपूर्ण डिज़ाइन है। मेरे उदाहरण कोड में 'your_own_defined_exception' नामक * तीसरा * अपवाद देखें। मैंने कहा कि इसे अंततः 'std :: अपवाद 'से लिया जाना है। – Nawaz

1

मुख्य रूप से क्योंकि जब आप अन्य लोगों के साथ काम करते हैं तो आपको इस बात पर सहमत होना होगा कि क्या पकड़ना है। अगर मैं const std::exception& पकड़ने की कोशिश करता हूं और आप const char* फेंकते हैं, तो मैं आपकी सामग्री को पकड़ने वाला नहीं हूं और बुरी चीजें हो सकती हैं।

इससे कोई फर्क नहीं पड़ता कि किस प्रकार का फेंक दिया जाता है और पकड़ा जाता है, जब तक कि हर कोई इससे चिपक जाता है। मुझे लगता है कि std::exceptionconst char* पर चुना गया है क्योंकि यह आपको अपवाद ऑब्जेक्ट में केवल एक स्ट्रिंग से अधिक रखने की अनुमति देता है। यह सिर्फ अधिक लचीला है।

2

यदि आप इसे अपने कोड में नियम बनाते हैं तो केवल std :: अपवाद से प्राप्त अपवाद फेंकने के बाद उन्हें पकड़ना आसान होता है। दूसरे शब्दों में आप सिर्फ std :: अपवाद पर एक पकड़ खंड हो सकता है:

catch (std::exception& e) 
{ 
    log_message(e); 
    throw; 
} 

लेकिन अगर आप इस नियम का पालन नहीं करते तो आप अंत पकड़ खंड लिखने के लिए आपको की जरूरत नहीं है जब हो रही है।वह अन्य उत्तर से

+0

प्रत्येक परत पर पकड़ने और पुनर्स्थापित करने के लिए बहुत कम लाभ होता है, यदि आपके पास वास्तव में कुछ करने के लिए कुछ है (और सी ++ में, RAII के साथ, यह दुर्लभ होना चाहिए) या इसे "निगल" करने के लिए केवल 'पकड़' खंड का उपयोग करें। –

+0

मुझे उन अपवादों के लिए एक स्टैक ट्रेस उत्पन्न करने के लिए उपयोगी लगता है, जिनकी अपेक्षा नहीं की जाती है। यह किसी त्रुटि का निदान करने और ट्रैकिंग को अपवादित करने में सहायता करता है। – sashang

+0

मैं मानता हूं कि ढेर उपयोगी हैं, हालांकि आपके दृष्टिकोण में दो डाउनसाइड्स हैं। सबसे पहले यह कोड को अव्यवस्थित करता है, अपवाद के मामले में * * विशिष्ट * कार्रवाई की जानी चाहिए, यह अब स्पष्ट नहीं है। दूसरा यह एक प्रदर्शन हॉग है, क्योंकि जीसी या क्लैंग जैसे लोकप्रिय कंपाइलर्स द्वारा उपयोग किए जाने वाले शून्य लागत अपवाद कार्यान्वयन को फेंकने पर कठोर दंड मिलता है। अन्य हैं, और मुझे बेहतर, विकल्प मिलते हैं। फेंकने के बिंदु पर ढेर को पकड़ने के लिए प्लेटफार्म विशिष्ट कोड एक है; दूसरा एक "नोट्स" लॉग इन करने के लिए आरएआईआई का उपयोग करना है जो अनचाहे के दौरान अपवाद में जोड़ा जाता है। –

1

एक अतिरिक्त बिंदु यह है -

आप एक पूर्णांक या एक स्ट्रिंग फेंक और आप एक विशिष्ट त्रुटि आप नहीं कर सकते को पकड़ने के लिए चाहते हैं। आपको सभी "int" अपवादों को पकड़ना होगा और फिर उन लोगों की तुलना करना होगा जिन्हें आप पकड़ना चाहते हैं, और फिर किसी भी को फिर से निकालने के लिए तैयार नहीं हैं। यदि आप अपवाद से प्राप्त होते हैं तो आप उस विशिष्ट अपवाद को पकड़ सकते हैं जिसे आप संभालना चाहते हैं और अभी भी लाभ है कि आप केवल std :: अपवाद पकड़ सकते हैं यदि आप उन्हें सभी संभालना चाहते हैं।

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