2011-01-10 17 views
10

मान लीजिए मुझे विरासत से भरा सी ++ लाइब्रेरी दी गई है। मुझे एक समारोह में Base* दिया गया है जब मुझे पता है कि यह वास्तव में Derived ऑब्जेक्ट और Derived को Base विरासत में इंगित कर रहा है। लेकिन मुझे नहीं पता कि यह किस प्रकार की विरासत है (सार्वजनिक/संरक्षित/निजी)। मुझे यह भी नहीं पता कि पदानुक्रम में कोई वर्चुअल फ़ंक्शन है या नहीं।static_cast बनाम गतिशील_कास्ट

स्रोत कोड/प्रलेखन Base और Derived की, जो डाली का उपयोग करना चाहिए की जांच कर रहे बिना इस स्थिति, को देखते हुए? या क्या मुझे बहुरूपता के बारे में सुनिश्चित करने के लिए पहले कोड/दस्तावेज़ीकरण से परामर्श लेना चाहिए?

पृष्ठभूमि

मैं क्यूटी 4.7 में QMainWindow की changeEvent समारोह लिख रहा हूँ। changeEvent फ़ंक्शन QEvent* लेता है जिसे मैं QEvent::type() जानकर अन्य प्रकार में डाल सकता हूं। मैं सोच रहा था कि मुझे static_cast या dynamic_cast का उपयोग करना चाहिए।

धन्यवाद।

+3

यदि आपके द्वारा उपयोग की जाने वाली कोई भी लाइब्रेरी 'संरक्षित' विरासत का उपयोग करती है, तो यह एक बेहतर लिखित लाइब्रेरी खोजने का समय है। –

+0

यह प्रश्न मदद कर सकता है: http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs- गतिशील-cast –

+2

@Zac: इच्छा है कि मैं टिप्पणियों को कम कर सकता हूं। यदि आप नहीं जानते कि लाइब्रेरी क्या करती है तो आप संभवतया कैसे निर्णय ले सकते हैं कि सुरक्षित विरासत नौकरी के लिए सही उपकरण है या नहीं? – Puppy

उत्तर

17

static_cast का उपयोग करें। यदि आप जानते हैं कि Base*Derived पर इंगित करता है, तो static_cast का उपयोग करें। dynamic_cast उपयोगी है जब यह व्युत्पन्न हो सकता है।

+1

अब आप जानते हो सकते हैं। लेकिन वह एक पुस्तकालय का उपयोग कर रहा है और मुझे यकीन है कि लाइब्रेरी द्वारा प्रदान की गई कोई गारंटी नहीं है कि वे कार्यान्वयन विवरण नहीं बदलेंगे। इंटरफ़ेस बेस * है, इसलिए ** ** ** आप मान सकते हैं। इसलिए आपको ** डायनामिक_कास्ट <> का उपयोग करना चाहिए ताकि आप यह जांच सकें कि आपकी धारणाएं बाद में हैं। –

+0

@ मार्टिन: यह उसकी समस्या है, मेरा नहीं। यदि वह * जानता है कि यह वास्तव में व्युत्पन्न को इंगित करता है, तो उस ज्ञान की जड़ उस सीमा से बाहर है जिसका मैं संभवतः उत्तर दे सकता हूं। – Puppy

+2

प्रोबेलम वह नहीं जानता है। उनका ज्ञान इस विशेष घटना के समय अंतरिक्ष समन्वय तक ही सीमित है। इस प्रकार हमें इस बात पर जोर देना होगा कि ओपी उनकी धारणा में गलत है कि वह जानता है। वह अब जानता है लेकिन ज्ञान भविष्य में हस्तांतरणीय नहीं है। इस प्रकार क्योंकि वह गलत है static_cast गलत जवाब है (यदि ओपी सही था तो यह सही जवाब है (लेकिन वह नहीं है))। एकमात्र समय जब आप इंटरफ़ेस मान सकते हैं तो व्युत्पन्न होता है जब यह व्युत्पन्न होता है * अन्यथा यह बेस * से व्युत्पन्न कुछ भी वापस कर सकता है (यही कारण है कि हमारे पास कोड में इंटरफेस हैं)। –

3

MSDN से -

सामान्य तौर पर आप इस तरह तैरता को ints या ints को enums रूप से जब आप में संख्यात्मक डेटा प्रकार परिवर्तित करना चाहते हैं static_cast उपयोग करते हैं, और आप रूपांतरण में शामिल डेटा प्रकार के कुछ कर रहे हैं। static_cast रूपांतरण डायनामिक_कास्ट रूपांतरणों के रूप में सुरक्षित नहीं हैं, क्योंकि static_cast कोई रन-टाइम प्रकार की जांच नहीं करता है, जबकि गतिशील_कास्ट करता है। एक संदिग्ध सूचक के लिए एक गतिशील_कास्ट विफल हो जाएगा, जबकि एक static_cast वापस आती है जैसे कुछ भी गलत नहीं था; यह खतरनाक हो सकता है। हालांकि गतिशील_कास्ट रूपांतरण सुरक्षित हैं, गतिशील_कास्ट केवल पॉइंटर्स या संदर्भों पर काम करता है, और रन-टाइम प्रकार की जांच एक ओवरहेड है।

अधिक जानकारी के लिए, बाहर की जाँच इस link

8

संदेह होने पर, आप dynamic_cast को प्राथमिकता देनी चाहिए। यह धीमा हो सकता है, लेकिन आप शायद वैसे भी अंतर नहीं देखेंगे।

template <typename Derived, typename Base> 
Derived safe_static_cast(Base b) 
{ 
    assert((void*)dynamic_cast<Derived>(b) && "safe_static_cast failed!"); 
    return static_cast<Derived>(b); 
} 

या कुछ बराबर:

आप गति की जरूरत है, निम्नलिखित स्निपेट का उपयोग करें।

विचार यह है कि डीबग बिल्ड में, यह जांचता है कि यह वास्तव में आपने सोचा था कि यह होगा, और यह रिलीज जारी करता है ... अच्छी तरह से सब कुछ पहले ही परीक्षण किया जा चुका है, है ना?

+1

आपको '(शून्य *)' कास्ट की आवश्यकता नहीं है –

+0

@ जीन: यह स्वीकार्य रूप से बदसूरत है :) मैं संदर्भ मामले के लिए ओवरलोडिंग से बचने की कोशिश कर रहा था। –

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