2011-04-20 15 views
7
the C++ FAQ के अनुसार

, जब एक एक वस्तु फेंकता है, यह स्थिर अभिव्यक्ति के प्रकार का उपयोग कर फेंक दिया है। इसलिए, अगर आप:स्थिर प्रकार फेंकने के लिए तर्क?

catch (some_exception const &e) { 
    // ... 
    throw e; // throws static type, possibly causing "slicing"; should just "throw;" instead 
} 

और eवास्तव में कुछ वर्ग some_exception से प्राप्त करने के लिए एक संदर्भ है, ऊपर throw कारण होगा "कटा हुआ" होने के लिए वस्तु चुपचाप। हां, मुझे पता है कि सही उत्तर throw; पर है, लेकिन जिस तरह से चीजें भ्रम और बग के अनावश्यक स्रोत की तरह लगती हैं।

इसके लिए तर्क क्या है? नहीं होगा, आप इसे गतिशील ऑब्जेक्ट के प्रकार से फेंकना चाहते हैं?

उत्तर

4

throw पर "तर्क" एक अभिव्यक्ति है और यह अभिव्यक्ति का प्रकार है जो अपवाद वस्तु को फेंकने का प्रकार निर्धारित करता है। फेंकने वाली अभिव्यक्ति का प्रकार आवश्यक रूप से एक पॉलीमोर्फिक प्रकार नहीं होना चाहिए, इसलिए यह निर्धारित करने का कोई तरीका नहीं हो सकता है कि अभिव्यक्ति वास्तव में अधिक व्युत्पन्न प्रकार के बेस क्लास सबोबजेक्ट को संदर्भित करती है या नहीं।

सरल "अभिव्यक्ति का प्रकार" नियम का भी अर्थ है कि कार्यान्वयन को रनटाइम पर अपवाद ऑब्जेक्ट का आकार और प्रकार गतिशील रूप से निर्धारित करने की आवश्यकता नहीं है, जिसके लिए अपवाद हैंडलिंग के लिए उत्पन्न होने के लिए अधिक जटिल और कम कुशल कोड की आवश्यकता हो सकती है । अगर इसे ऐसा करना होता है तो यह उस भाषा में एकमात्र जगह का प्रतिनिधित्व करेगा जहां कॉल पॉइंट पर अज्ञात प्रकार के लिए एक प्रतिलिपि बनाने की आवश्यकता थी। यह कार्यान्वयन की लागत में महत्वपूर्ण रूप से जोड़ सकता है।

9

जब आप throw कुछ करते हैं, throw के संचालन से एक अस्थायी वस्तु का निर्माण किया जाता है और वह अस्थायी वस्तु पकड़ा जाता है।

सी ++ में चीजों की प्रतिलिपि बनाने या अभिव्यक्ति के गतिशील प्रकार के आधार पर वस्तुओं को बनाने के लिए अंतर्निहित समर्थन नहीं है, इसलिए अस्थायी वस्तु ऑपरेंड के स्थिर प्रकार का है।

+0

लेकिन अगर आप संदर्भ द्वारा पकड़ने, ऐसा लगता है यह बस सब पर किसी भी प्रतिलिपि कर के बिना एक ही वस्तु rethrow सकता है प्रतीत होता है (जैसे "फेंक," करता है)। –

+4

फिर 'फेंक x;' इसके ऑपरेंड के आधार पर अलग-अलग व्यवहार करता है और क्या यह 'कैच' ब्लॉक में दिखाई देता है। 'फेंक x 'से होने का लाभ' फेंक 'से अलग है,' यह है कि 'फेंक x' का व्यवहार हमेशा समान होता है (एक प्रतिलिपि बनाई जाती है और वह प्रतिलिपि पकड़ी जाती है), लेकिन आपके पास अभी भी क्षमता है यदि आप ऐसा करना चाहते हैं तो वर्तमान अपवाद को फिर से करें। [मुझे शायद यह ध्यान रखना चाहिए कि कुछ परिस्थितियों में प्रतिलिपि को बढ़ाया जा सकता है, लेकिन केवल ऐसा करने पर, रचनाकारों और विनाशकों के आह्वान से प्रोग्राम के व्यवहार को अलग नहीं किया जाता है।] –

+0

+1 अच्छा स्पष्टीकरण। :-) – Nawaz

0

पर विचार करें हम वस्तुओं के लिए संदर्भ हो सकता है जहां संदर्भ के स्थिर प्रकार copyable है, लेकिन वस्तु के गतिशील प्रकार नहीं है।

struct foo {}; 

struct ncfoo : foo 
{ 
private: 
    ncfoo(ncfoo const&) {} 
}; 

ncfoo g_ncfoo; 

void fun() 
{ 
    foo& ref = g_ncfoo; 
    throw ref; // what should be thrown here? 
} 

तुम कहते हो, तो कैसे सटीक नियम हैं "इस मामले में सिर्फ स्थिर प्रकार फेंक" - क्या "इस मामले में" मतलब है? जिन संदर्भों को हमने अभी पकड़ा है उन्हें प्रतिलिपि के बिना "फिर से फेंक दिया गया" है, बाकी सब कुछ कॉपी किया गया है? एचएम ...

लेकिन हालांकि आप नियम को परिभाषित करते हैं, फिर भी यह भ्रमित हो जाएगा। संदर्भ के आधार पर फेंकने से अलग-अलग व्यवहार होते हैं, इस पर निर्भर करते हुए कि हमें उस संदर्भ के बारे में बताया गया है। NEH। सी ++ पहले से ही जटिल और काफी भ्रामक :) है

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