2011-04-21 18 views
14

यह मेरा साक्षात्कार प्रश्न था।एक कन्स्ट्रक्टर को संभालने का अपवाद

आश्चर्य की बात है कि मैंने कभी इस तरह के सवाल के बारे में सोचा नहीं।

क्या हमारे पास एक निर्माता सी ++ के अंदर अपवाद हैंडलिंग हो सकता है?

तनाव में और बहुत कुछ नहीं सोचते मैंने कहा "हाँ हम शायद इसे एक निर्माता में कर सकते हैं .लेट्स का कहना है कि हम एक नए सूचक का उपयोग करके एक सूचक सदस्य को कुछ स्मृति आवंटित कर रहे हैं और यह एक खराब आवंटन अपवाद फेंकता है, इस तरह से उठाए जा रहे अपवादों की संभावना "

बाद में मैंने सोचा कि निर्माता कभी भी मूल्य वापस नहीं कर सकते हैं। तो एक कन्स्ट्रक्टर के अंदर एक अपवाद कैसे पकड़ा जा सकता है। अब मैं खुद से यह पूछ रहा हूं!

क्या कोई मुझे इस भ्रम से बाहर निकलने में मदद कर सकता है?

+0

आप निर्माता में नहीं, बुला कोड में अपवाद को पकड़ने होगा। – helpermethod

+3

रिसेप्शन वैल्यू के रूप में अपवाद वापस नहीं लौटाए जाते हैं, वे पहले उचित पकड़ ब्लॉक में स्टैक को छोड़ देते हैं, इसलिए जब आप कन्स्ट्रक्टर से कोई मान वापस नहीं कर सकते हैं तो आप इससे अपवाद फेंक सकते हैं। – forsvarir

+0

@ हेल्पर विधि: यदि आपने कन्स्ट्रक्टर में स्मृति आवंटित की है तो आप निश्चित रूप से निर्माता में अपवाद को पकड़ना चाहते हैं ताकि आप स्मृति को आवंटित कर सकें (फिर शायद फिर से फेंक दें)। लेकिन ऑब्जेक्ट को केवल एक ऑब्जेक्ट पर गतिशील रूप से आवंटित करने के लिए यह स्मार्ट है, इसलिए आपको इस मैन्युअल प्रकार के क्लीनअप को करने की आवश्यकता नहीं है। –

उत्तर

12

यह GOTW Constructor Failures प्रश्न देखें जो आपकी क्वेरी को कुछ हद तक संबोधित करता है और कहता है कि यह समय बर्बाद है।

+3

+1 मैं फ़ंक्शन-ट्राई-ब्लॉक के बारे में एक विकल्प और इसकी कई त्रुटियों के बारे में लिखने जा रहा था, लेकिन मैं सटर के विवरण के करीब नहीं आऊंगा :) –

+0

यह एक बहुत ही रोचक लेख था, +1 +1 – Justin

-2

सी ++ में अन्य भाषाओं के समान प्रयास करने की कोशिश की गई है। एक ट्यूटोरियल ऑनलाइन पाया जा सकता: http://www.cplusplus.com/doc/tutorial/exceptions/

संपादित करें: उदाहरण के लिए पूरी तरह से काम कर रहे कोड में बदल गया

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    void f(){ 
    throw 10; 
    } 

    A(){ 
    try{ 
     f(); 
    } 
    catch(int e){ 
     cout << "Exception caught\n"; 
    } 
    } 
}; 

int main (int argc, const char * argv[]) 
{ 

    A a; 
    return 0; 
} 

यह पैदा करता है उत्पादन:

Exception caught 
+0

@ laas.i पता है कि बहुत सारे दस्तावेज हैं। लेकिन मैं विशेष रूप से एक निर्माता में अपवाद हैंडलिंग के बारे में पूछ रहा हूं। यह मेरे प्रश्न को पूरा नहीं करता है। – Vijay

+0

सी ++ में 'आखिरकार' ब्लॉक नहीं हैं, और सी ++ में अपवाद हैंडलिंग जावा जैसे भाषाओं से कई तरीकों से अलग है। क्लीनअप के लिए, सी ++ का उपयोग http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – helpermethod

+0

@ हेल्पर विधि - आप निश्चित रूप से 'आखिरकार' के बारे में सही हैं, लेकिन जैसा कि मैंने इसे समझ लिया है, @ ज़ोंबी ने ** कन्स्ट्रक्टर के अंदर अपवाद हैंडलिंग ** के बारे में पूछा है, इसलिए मेरा उदाहरण अभी भी मान्य है या प्रश्न को सही किया जाना चाहिए। मैं अपने कोड को और कोड के साथ अद्यतन करता हूं। – Laas

2

कंस्ट्रक्टर्स एक वापसी प्रकार नहीं है, इसलिए कोड का उपयोग करना संभव नहीं है। सिग्नल विफलता को सिग्नल करने का सबसे अच्छा तरीका अपवाद फेंकना है। यदि आपके पास अपवादों का उपयोग करने का विकल्प नहीं है, तो "कम से कम खराब" कार्य-आसपास ऑब्जेक्ट को द्वारा "ज़ोंबी" स्थिति में एक आंतरिक स्थिति बिट सेट करना है ताकि ऑब्जेक्ट इस प्रकार की तरह कार्य करता है मृत भले ही यह तकनीकी रूप से जीवित है।

आप कन्स्ट्रक्टर के भीतर नहीं, कॉलिंग कोड में अपवाद पकड़ लेंगे।

अधिक जानकारी के लिए How can I handle a constructor that fails? देखें (वास्तव में, मैं अपवाद हैंडलिंग के बारे में पूरे पृष्ठ को पढ़ने का सुझाव देता हूं, वास्तव में प्रबुद्ध)।

+0

मैंने इसे पढ़ा। लेकिन मैं कुछ व्यावहारिक तरीकों की उम्मीद कर रहा हूं जो लोग इस तरह के परिदृश्यों में उपयोग करते हैं। – Vijay

+1

+1, हालांकि किसी को यह कहना है कि सवाल एक चाल प्रश्न का थोड़ा सा है। आम तौर पर जब आप किसी तरह से विफल हो जाते हैं तो आप केवल एक कन्स्ट्रक्टर के अंदर फेंकते हैं, अन्य विफलताओं को संभालने के लिए एक कन्स्ट्रक्टर के अंदर कोशिश/पकड़ना पूरी तरह से संभव है और पहले स्थान (या, पुनर्स्थापना) में कन्स्ट्रक्टर की विफलता से बचने के लिए पूरी तरह से संभव है। स्थिति के आधार पर, यह प्राथमिक हो सकता है। उदाहरण के लिए, यदि आप अपने कन्स्ट्रक्टर में दो ऑब्जेक्ट्स बनाते हैं, और दूसरा Bad_alloc फेंकता है, तो आप क्या करते हैं? कॉलिंग कोड में अपवाद को पकड़ने से पहले ऑब्जेक्ट को रिसाव कर दिया जाएगा। कन्स्ट्रक्टर के अंदर हैंडलिंग इस से बचाता है। – Damon

+0

@ ज़ोंबी: क्या परिदृश्य? एक निर्माता से एक अपवाद फेंक दिया जा रहा है? एक निर्माता विफलता? एक निर्माता जो अपवाद पकड़ रहा है? – forsvarir

0

अपवाद हैंडलिंग और वापसी प्रकार पूरी तरह से अलग हैं। जब प्रोग्राम को कन्स्ट्रक्टर में अपवाद मिलता है, तो यह कैच ब्लॉक [अगर उपयोग किया जाता है] या कॉलर (मुख्य()) पर फेंक दिया जाता है। इस मामले में, हमारे पास कन्स्ट्रक्टर में पकड़ ब्लॉक है और इसके द्वारा संभाला गया अपवाद है। एक बार अपवाद संभालने के बाद, कन्स्ट्रक्टर/फ़ंक्शन में शेष बयान निष्पादित करना शुरू कर दिया जाएगा। नीचे उदाहरण देखें,

class A 
{ 
    public: 
    A(){ 
     printf("Hi Constructor of A\n");   
    try 
    { 
     throw 10; 
    } 
    catch(...) 
    { 
     printf("the String is unexpected one in constructor\n"); 
    } 
    printf("Hi Constructor of A\n"); 
} 
    ~A(){ 
    printf("Hi destructor of A\n"); 
} 
}; 

int main() 
{ 

try{ 
    A obj ; 
    throw "Bad allocation"; 
} 
catch(int i) 
{ 
    printf("the Exception if Integer is = %d\n", i); 
} 
catch(double i) 
{ 
    printf("the Exception if double is = %f\n", i); 
} 
catch(A *objE) 
{ 
    printf("the Exception if Object \n"); 
} 
catch(...) 
{ 
    printf("the Exception if character/string \n"); 
} 
printf("Code ends\n"); 
return 0; 
} 

इस उत्पादन का उत्पादन:

Start: Constructor of A 
the String is unexpected one in constructor 
End: Constructor of A 
Hi destructor of A 
the Exception if character/string 
Code ends 
संबंधित मुद्दे