2011-03-16 10 views
8

मुझे पता है कि क्लास पदानुक्रम में "क्रॉस-कास्ट" करने के लिए dynamic_cast का उपयोग करना कानूनी है। उदाहरण के लिए, इस तरह दिखेगा कि अगर मैं श्रेणियां होती हैं:जांच कर रहा है कि एक क्रॉस-कास्ट संभवतः काम कर सकता है या नहीं?

A B 
    \/
    C 

अगर मैं एक A* सूचक है कि प्रकार C की एक वस्तु की ओर इंगित करता रहा है, तो मैं

A* aPtr = /* ... something that produces a C* ... */ 
B* bPtr = dynamic_cast<B*>(aPtr); 

उपयोग कर सकते हैं करने के लिए एक सूचक प्राप्त करने के लिए BC का मूल उद्देश्य मैं इंगित कर रहा हूं।

कारण मैं यह उल्लेख है कि समय है कि मैं इसके बाद के संस्करण कोड लिखने पर, यह संभव है कि संकलक अभी तक C की परिभाषा भले ही यह A और B देखा है नहीं देखा गया है। इसका अर्थ यह है कि यह संभव है कि संकलक A और B के बीच किसी भी प्रकार के कनेक्शन का पता नहीं लगाता है, लेकिन इसे अभी भी कोड को संकलित करना है क्योंकि किसी भी परिस्थिति में सफल होने के लिए C जैसे वर्ग और dynamic_cast के लिए यह संभव है।

समस्या यह है कि इसका मतलब है कि मैं गलती से गलत प्रकार की वस्तु को पार कर सकता हूं। मान लीजिए मैं वर्गों है कि इस तरह लग रहे है:

A B D 
\/ 
    C 

यहाँ, D कुछ यादृच्छिक असंबंधित वर्ग है।

A* aPtr = /* ... get a C* pointer ... */ 
D* dPtr = dynamic_cast<D*>(aPtr); 

फिर इस dynamic_cast हमेशा की तरह, कार्यावधि में असफल हो जायेगी वहाँ के बाद से A और D कनेक्ट करने के लिए कोई संभव तरीका नहीं: मैं कुछ इस तरह लिखने की कोशिश है। अगर मैं D गलती से उपयोग कर रहा हूं क्योंकि मेरा मतलब B का उपयोग करना था, तो संकलक मुझे कोई संकेत नहीं देगा कि मेरे पास एक अर्थहीन कलाकार है।

मेरा प्रश्न है: क्या कोई तरीका है कि मैं संकलक को चेतावनी दे सकता हूं कि कलाकार हमेशा रनटाइम पर असफल रहेगा? मैं किसी भाषा-स्तरीय समाधान या किसी भी बड़े कंपाइलर के लिए कुछ कंपाइलर सेटिंग से खुश हूं जो इसका पता लगा सकता है। यदि कोई बाहरी उपकरण है, तो यह भी ठीक है; मैं सिर्फ यह जानना चाहता हूं कि त्रुटियों के इस वर्ग को पकड़ना संभव है या नहीं।

+0

यह निश्चित रूप से लिंकर स्तर होना चाहिए? संकलन समय पर, आप नहीं जानते कि एक वर्ग बनाया जा सकता है जो 'ए' और' डी' से प्राप्त होता है? – Keith

+0

@ कीथ- निश्चित रूप से, जब तक कि आपके पास सर्वज्ञानी संकलक नहीं है। मैन, मैं उनमें से एक चाहता हूं ... :-) – templatetypedef

+0

@ किथ: यहां तक ​​कि मेरे उत्तर में समझाए गए लिंकर को सभी प्रकार के बारे में पूरी जानकारी नहीं हो सकती है। –

उत्तर

3

संकलन समय पर इसका पता लगाना संभव नहीं है। वर्ग C जो संबंध पेश करता है एक गतिशील रूप से लोड करने योग्य लाइब्रेरी में पाया जा सकता है जिसे अभी तक लिखा नहीं गया है, और संकलक अन्यथा साबित नहीं कर सकता है।

हालांकि कुछ अपवाद हो सकते हैं।यदि A में केवल निजी निर्माता (या एक निजी विनाशक) हैं तो संकलक निश्चित हो सकता है कि कोई नया सबक्लास नहीं होगा जिसे A द्वारा मित्रों के रूप में नामित नहीं किया गया है।

+0

यह निश्चित रूप से सच है। हालांकि, क्या किसी भी तरह से लिंकर को मुझे कुछ चेतावनी देने के लिए संभव होगा "हे, बस आपको यह बताने के लिए कि यह संदिग्ध लगता है?" भले ही यह कोई समस्या न हो? – templatetypedef

+1

@templatetypedef: चूंकि 'dynamic_cast' दिखता है और टेम्पलेट फ़ंक्शन की तरह लगता है, शायद आप एक रैपर पेश कर सकते हैं, रैपर के उपयोग को मजबूर करने के लिए '# गतिशील_कास्ट चेक_डोनिक_कास्ट' का उपयोग करें, और फिर किसी भी तरह टेम्पलेट के सभी तत्काल संस्करणों की एक सूची प्राप्त करें ? विरासत ग्राफ प्राप्त करना काफी आसान है, उदाहरण के लिए डॉक्सिजन के एक्सएमएल आउटपुट सहित कई टूल हैं जो इसका पर्दाफाश करते हैं। उस जानकारी को जोड़कर और कुछ हेरिस्टिक को लागू करने से आपको वह चेतावनी मिलनी चाहिए जो आप चाहते हैं। –

-3

सत्य तब होता है जब आप dynamic_cast का उपयोग करते हैं, तो आप किसी भी पॉलिमॉर्फिक प्रकार पॉइंटर को किसी भी पॉलिमॉर्फिक प्रकार पॉइंटर में डाल सकते हैं, भले ही कक्षाएं एक-दूसरे से असंबंधित हों।

यदि आप संकलन-समय की जांच करना चाहते हैं तो आपको अन्य जानवरों का उपयोग करने की आवश्यकता है - static_cast या निहित रूपांतरण - जो कई मामलों में कुछ अन्य कारणों के अनुरूप नहीं हो सकता है।

dynamic_cast पर हम जिस समाधान का उपयोग करते हैं, वह एक टेम्पलेटेड फ़ंक्शन है जो dynamic_cast करता है और एक नल पॉइंटर प्राप्त होने पर अपवाद फेंकता है। यह निश्चित रूप से केवल रनटाइम चेक है, लेकिन यह अपेक्षाकृत विश्वसनीय है।

+1

-1: आप एक पॉलिमॉर्फिक क्लास को केवल अन्य पॉलिमॉर्फिक क्लास में डायनामिक_कास्ट कर सकते हैं यदि उनके आरटीटीआई संबंधित हैं। अन्यथा आपको 0 पीआरटी मिलती है (यदि आप पीआरटी पर जाते हैं), या यदि आप गैर संबंधित पॉलिमॉर्फिक कक्षा में रेफरी करते हैं तो आपको खराब_कास्ट अपवाद मिलता है। – TrueY

0

यह गतिशील कलाकार का पूरा अर्थ है: यह गतिशील है यानी यह संकलन समय पर रनटाइम पर चेक किया गया है।

कंपाइलर केवल जांचता है कि जाली कक्षाएं पॉलिमॉर्फिक हैं या नहीं। यदि कक्षाएं पॉलिमॉर्फिक नहीं हैं तो रनटाइम पर कास्टिंग की जांच करने के लिए पर्याप्त जानकारी नहीं होगी।

और आखिर में गतिशील कलाकार के बाद कार्यक्रम को जांचना चाहिए कि प्राप्त पॉइंटर शून्य नहीं है या नहीं। यदि आप किसी संदर्भ में आते हैं तो आपको std :: bad_cast पकड़ना चाहिए।

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