अंतर: std :: runtime_error बनाम std :: अपवाद ()


127

बीच क्या अंतर है std::runtime_errorऔर std::exception? प्रत्येक के लिए उपयुक्त उपयोग क्या है? वे पहली जगह में अलग क्यों हैं?

जवाबों:


152

std::exceptionवह वर्ग है जिसका एकमात्र उद्देश्य अपवाद पदानुक्रम में आधार वर्ग के रूप में सेवा करना है। इसका कोई अन्य उपयोग नहीं है। दूसरे शब्दों में, अवधारणात्मक रूप से यह एक अमूर्त वर्ग है (भले ही इसे शब्द के C ++ अर्थ में सार वर्ग के रूप में परिभाषित नहीं किया गया है)।

std::runtime_errorstd::exceptionविभिन्न रनटाइम त्रुटियों के मामले में फेंकने के इरादे से एक अधिक विशिष्ट वर्ग है । इसका दोहरा उद्देश्य है। यह अपने आप फेंका जा सकता है, या यह एक आधार वर्ग के रूप में विभिन्न और भी अधिक विशिष्ट प्रकार के रनटाइम त्रुटि अपवादों, जैसे std::range_error, std::overflow_errorआदि के लिए काम कर सकता है। आप अपने स्वयं के अपवाद वर्गों को अवरोही से std::runtime_errorपरिभाषित कर सकते हैं, साथ ही साथ आप अपने स्वयं के अपवाद को परिभाषित कर सकते हैं। से उतरने वाली कक्षाएं std::exception

ठीक उसी तरह std::runtime_error, जैसे मानक पुस्तकालय में होता है std::logic_error, उससे भी नीचे उतरता है std::exception

इस पदानुक्रम के होने का मतलब उपयोगकर्ता को C ++ अपवाद हैंडलिंग तंत्र की पूर्ण शक्ति का उपयोग करने का अवसर देना है। चूंकि 'कैच' क्लॉज़ बहुरूपी अपवादों को पकड़ सकता है, इसलिए उपयोगकर्ता 'कैच' क्लॉस लिख सकता है जो अपवाद पदानुक्रम के एक विशिष्ट उपप्रकार से अपवाद प्रकारों को पकड़ सकता है। उदाहरण के लिए, सबट्री catch (std::runtime_error& e)से सभी अपवादों को std::runtime_errorपकड़ेंगे, जिससे अन्य सभी को गुजरने में मदद मिलेगी (और कॉल स्टैक को आगे बढ़ाएं)।

पुनश्च एक उपयोगी अपवाद श्रेणी पदानुक्रम डिजाइन करना (जो आपको केवल आपके कोड के प्रत्येक बिंदु पर आपकी रुचि के अपवाद प्रकारों को पकड़ने देगा) एक गैर-तुच्छ कार्य है। मानक सी ++ लाइब्रेरी में आप जो देखते हैं, वह एक संभव दृष्टिकोण है, जो आपको भाषा के लेखकों द्वारा पेश किया जाता है। जैसा कि आप देखते हैं, उन्होंने सभी अपवाद प्रकारों को "रनटाइम त्रुटियों" और "तर्क त्रुटियों" में विभाजित करने का निर्णय लिया और आपको अपने अपवाद प्रकारों के साथ वहां से आगे बढ़ने दिया। बेशक, पदानुक्रम की संरचना के वैकल्पिक तरीके हैं, जो आपके डिजाइन में अधिक उपयुक्त हो सकते हैं।

अपडेट: पोर्टेबिलिटी लिनक्स बनाम विंडोज

जैसा कि लोकी एस्टारी और unixman83 ने अपने जवाब और टिप्पणियों में नीचे उल्लेख किया है, exceptionवर्ग का निर्माता सी ++ मानक के अनुसार कोई तर्क नहीं लेता है। Microsoft C ++ में exceptionक्लास में तर्क देने वाला एक कंस्ट्रक्टर है , लेकिन यह मानक नहीं है। runtime_errorकक्षा एक निर्माता लेने तर्कों (है char*दोनों प्लेटफार्मों, विंडोज और लिनक्स पर)। पोर्टेबल होने के लिए, बेहतर उपयोग runtime_error

(और याद रखें, सिर्फ इसलिए कि आपकी परियोजना का एक विनिर्देश कहता है कि आपके कोड को लिनक्स पर नहीं चलना है, इसका मतलब यह नहीं है कि इसे लिनक्स पर कभी नहीं चलना है।)


1
धन्यवाद। बहुत बढ़िया जवाब। हालांकि मुझे आश्चर्य है कि अगर कभी भी अलग-अलग प्रकार के अपवाद की आवश्यकता होती है ... बस एक विचार हालांकि।
शिवाबुध

1
यदि ऐसी कोई सामर्थ्य है कि अपवाद को फिर से कवर किया जा सकता है, तो एक अलग प्रकार का अपवाद उपयोगी हो सकता है क्योंकि हम अपवाद हैंडलिंग तंत्र का उपयोग हैंडलर के अपवाद को निर्देशित करने के लिए कर सकते हैं जो कि कोशिश करेगा और समस्या को ठीक करेगा। यदि मानक अपवादों में से एक से भी वसूली का कोई मौका नहीं है, तो ठीक है।
मार्टिन यॉर्क

1
बस एक तरफ के रूप में: कोई नियम नहीं है, कहीं भी, जो आपको प्राप्त करने के लिए मजबूर करता है std::exception। निश्चित रूप से, सभी stdचीजें उसी के व्युत्पन्न वर्ग को फेंक देती हैं, लेकिन केवल std::exceptionव्युत्पन्न वस्तुओं को फेंकने का कोई कारण नहीं है ।
रुबेंव

1
@rubenvb मुझे इसके बारे में नहीं पता था, लेकिन मुझे लगता है कि यह भविष्य के रखरखाव के लिए कोड को स्पष्ट करेगा यदि केवल अपवाद से प्राप्त कक्षाओं की वस्तुओं को फेंक दिया जाता है। उदाहरण: मुझे यह पता लगाना पसंद है कि मेरे कोड बेस में कौन से कस्टम अपवाद लागू किए गए हैं और अपवाद से प्राप्त वर्गों की खोज करते हैं।
06

21

std::exceptionमाना जाना चाहिए (ध्यान दें) मानक अपवाद पदानुक्रम का सार आधार। ऐसा इसलिए है क्योंकि एक विशिष्ट संदेश में पास करने के लिए कोई तंत्र नहीं है (ऐसा करने के लिए आपको व्युत्पन्न और विशेषज्ञ होना चाहिए what())। आपको std :: अपवाद का उपयोग करने से रोकने के लिए कुछ भी नहीं है और सरल अनुप्रयोगों के लिए यह आपके लिए आवश्यक हो सकता है।

std::runtime_errorदूसरी ओर वैध कंस्ट्रक्टर हैं जो एक संदेश के रूप में एक स्ट्रिंग को स्वीकार करते हैं। जब what()एक कॉस्ट चार पॉइंटर कहा जाता है, तो एक सी स्ट्रिंग पर अंक दिए जाते हैं जिसमें वही स्ट्रिंग होता है जो कंस्ट्रक्टर में पारित किया गया था।

try
{
    if (badThingHappened)
    {
         throw std::runtime_error("Something Bad happened here");
    }
}
catch(std::exception const& e)
{
    std::cout << "Exception: " << e.what() << "\n";
} 

1
जवाब के लिए धन्यवाद मार्टिन। हालाँकि, मैं std :: अपवाद () का उसी तरह उपयोग करता हूं, जैसा आपने ऊपर वर्णित किया है। यानी std :: अपवाद () कंस्ट्रक्टर भी एक std :: string () या const char * ले सकता है।
शिवाबुध

14
मानक के अनुसार नहीं। std :: अपवाद में एक निर्माता है जो कोई तर्क नहीं लेता है। एक संस्करण का उपयोग करना जो एक std :: string या C-String स्वीकार करता है, गैर पोर्टेबल है।
मार्टिन यॉर्क

10
Microsoft की वजह से मुझे फेंकने की आदत पड़ गई std::exception(std::string)। अब मुझे एहसास हुआ कि std::runtime_errorअगर मुझे मेरा कोड लिनक्स (जीसीसी) में काम करना है तो मुझे फेंक देना चाहिए ।
unixman83
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.