2016-04-18 2 views
7

मान लीजिए मैं एक वर्गव्युत्पन्न वर्ग कन्स्ट्रक्टर पर कोई भी वादा नहीं: क्या इसका उपयोग बेस कन्स्ट्रक्टर पर ध्यान देने के बिना किया जा सकता है?

class C : public B { 
    public: 
    C() noexcept; 
} 

noexcept विनिर्देशक आधार वर्ग द्वारा एक ही वादा आवश्यकता होती है है? यही है, जब मैं अस्वीकरण का उपयोग करने पर विचार कर रहा हूं, तो क्या मैं सिर्फ सी :: सी() के व्यवहार को देखता हूं या क्या मुझे यह भी विचार करने की आवश्यकता है कि बी :: बी() अपवाद फेंक सकता है या नहीं?

उदाहरण के लिए, यदि बी :: बी अपवाद फेंकता है, तो क्या यह सी :: सी या उस कोड पर प्रचारित करता है जो एक नए वर्ग के उदाहरण के लिए पूछ रहा था? - यदि सी :: सी को प्रचारित किया जाता है, तो यह एक कारण होगा कि कन्स्ट्रक्टर के लिए कोई संदर्भ नहीं है यदि बेस क्लास कन्स्ट्रक्टर के लिए अस्वीकार्य नहीं है।

+0

बेसक्लस निर्माण विफल होने पर कक्षा निर्माण सफल हो सकता है? –

+0

नहीं। इसलिए, जब संकलक यह सब एक साथ रखता है, तो क्या यह प्रत्येक कन्स्ट्रक्टर को स्वतंत्र रूप से संभालता है, जिसका अर्थ यह है कि व्युत्पन्न वर्ग पर एक अस्वीकरण विनिर्देश का कोई प्रभाव नहीं पड़ता है कि संकलक बेस कन्स्ट्रक्टर का प्रबंधन कैसे करता है? – rsjaffe

+0

वास्तव में, मुझे लगता है कि मेरा प्रश्न भ्रामक हो सकता है। यदि आपका बेसक्लास 'वेक्टर' है और आप इसे शून्य आकार पास करते हैं, तो आप वास्तव में गारंटी दे सकते हैं कि कोई अपवाद फेंकता नहीं है। इसी तरह, 'अस्वीकरण' का अर्थ है कि कुछ फेंकना नहीं चाहिए, न कि 'abort() '(मुझे लगता है, कृपया दस्तावेज़ों का संदर्भ लें) का आह्वान किया जाता है। इसलिए, यदि बेस कन्स्ट्रक्टर पहले से ही 'अस्वीकरण' नहीं है, तो इसे 'try' - 'catch' में लपेटा जाना चाहिए, लेकिन यह' अस्वीकरण 'गारंटी को पूरा कर सकता है। –

उत्तर

6

तकनीकी रूप से † आधार वर्ग निर्माता की कोई आवश्यकता noexcept घोषित करने की नहीं है, लेकिन जब एक व्युत्पन्न निर्माता कि noexcept घोषित किया जाता है द्वारा कहा जाता है कि यह, फेंक नहीं करना चाहिए।

तो हाँ, आपको यह विचार करने की आवश्यकता है कि बेस क्लास कन्स्ट्रक्टर फेंक सकता है (अपवाद या अन्यथा)।

मुझे लगता है कि मेरा प्रश्न पूछने का एक बेहतर तरीका यह है: अपवाद कहां जाता है?

कॉल

इस तरह प्रवाह:

caller 
    -> derived constructor (the noexcept applies to this) 
    -> subobject constructors (includes bases) 
    - derived constructor body (not a call, but part of the derived constructor that is executed after the subobjects are constructed) 

तो, अगर एक subobject निर्माता फेंकता है (चाहे वह एक आधार या सदस्य होना), यह पहली व्युत्पन्न निर्माता है, जो न और करता है को जाता है †† अपवाद को निगल सकता है ताकि कन्स्ट्रक्टर को अस्वीकार न किया जाए, तो यह कॉलर को प्रचारित करेगा। लेकिन चूंकि यह है, std::terminate बुलाया जाता है।

तो आधार वास्तव में के रूप में आवश्यक व्युत्पन्न द्वारा, तो यह आवश्यकता को पूरा करता है और अपने आप में noexcept घोषित किया जा सकता तो वहाँ rarly कारण ऐसा करने के लिए नहीं है फेंक नहीं है †। शायद, यदि बेस क्लास लाइब्रेरी का हिस्सा है जिसे सी ++ 03 का समर्थन करना चाहिए, जबकि व्युत्पन्न कक्षा बाद के मानक को मान सकती है, तो यह समझ में आ जाएगा।

†† यह फ़ंक्शन-ट्राई-ब्लॉक से पकड़ सकता है, लेकिन वे हमेशा फिर से फेंक देंगे।

+1

आप एक अच्छा त्रुटि संदेश उत्पन्न करने के लिए 'सी' के सीटीआर पर फ़ंक्शन-ट्राई-ब्लॉक का उपयोग कर सकते हैं (हालांकि इसे प्रोग्राम को निरस्त करना होगा, पुनर्प्राप्त करने का कोई तरीका नहीं है) –

+0

@ एमएम ओह हाँ, मैं उन लोगों के बारे में भूल गया। मैंने अपने जवाब में एक नोट जोड़ा। – user2079303

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