2012-07-16 5 views
11

Scott Meyer अपनी पुस्तक Effective C++ में dynamic_cast का उपयोग सुरक्षित विरासत में या विरासत पदानुक्रम में करने के लिए किया जाता है। यही है, आप बेस क्लास ऑब्जेक्ट्स को प्वाइंटर्स या रेफरेंस में बेस क्लास ऑब्जेक्ट्स को संदर्भित करने या संदर्भित करने के लिए डायनामिक_कास्ट का उपयोग इस तरह से करते हैं कि आप यह निर्धारित कर सकें कि कैस्ट सफल हुए हैं या नहीं।डायनामिक_कास्ट ऑपरेटर का उपयोग कर असफल कैस्ट की पहचान कैसे करें?

असफल संकेतों को एक शून्य सूचक (जब कास्टिंग पॉइंटर्स) या अपवाद (संदर्भ कास्टिंग करते समय) द्वारा इंगित किया जाता है।

मैं दो कोड स्निपेट प्राप्त करना चाहता हूं जो कास्टिंग पॉइंटर और कास्टिंग संदर्भ के मामले में असफल कलाकार दिखा रहा है।

+4

क्या आप कोड के उदाहरण मांग रहे हैं जो जांचता है कि कोई सूचक शून्य है और कोड जो अपवाद को पकड़ता है? –

+0

नहीं। मुझे समझ में नहीं आता कि स्कॉट द्वारा वर्णित कैसा असफल हो सकता है। एक कोड स्निपेट निश्चित रूप से मदद करेगा। –

+1

http://en.wikipedia.org/wiki/Dynamic_cast –

उत्तर

21

संकेतों के लिए, यह एक साधारण नल की जांच है:

A* a = new A(); 
B* b = dynamic_cast<B*>(a); 

if (b == NULL) 
{ 
    // Cast failed 
} 

संदर्भ के लिए, आप पकड़ कर सकते हैं:

try { 
    SomeType &item = dynamic_cast<SomeType&>(obj); 
} 
catch(const std::bad_cast& e) { 
    // Cast failed 
} 
+0

@LinuxPenseur चेक यह मान रहा है कि "ए" का वैध मान है। आपको पहले यह जांचना होगा (आवंटन के लिए)। डायनामिक_कास्ट चेक यह जांच रहा है कि ए को सुरक्षित रूप से "बी" में डाला जा सकता है - इसलिए चेक 'N' के लिए' बी' के खिलाफ है - यानी: बी शून्य है और शून्य नहीं है। –

+0

@ रीडकोप्सी: मेरा 'सुरक्षित कलाकार' का क्या अर्थ है। किस स्थिति में बी पूर्ण हो सकता है? –

+1

'गतिशील_कास्ट' का उपयोग तब किया जाता है जब एक वर्ग पॉलिमॉर्फिक होता है (' वर्चुअल 'फ़ंक्शन होता है) और यह रन-टाइम चेक करता है, जो' न्यूल 'पॉइंटर लौटाता है। 'Dynamic_cast' का उपयोग करके आप इसे सी-स्टाइल रूपांतरणों के बजाय जो भी चाहते हैं उसे निष्पक्ष रूप से कह रहे हैं जहां यह विभिन्न प्रकार के रूपांतरणों की कोशिश करता है। 'dynamic_cast' का भी उपयोग तब किया जाता है जब आप ऑब्जेक्ट को परिवर्तित करने के लिए नहीं जानते हैं, 'static_cast'' के बजाय गैर-पॉलीमोप्रिक वर्गों के लिए उपयोग किया जाता है और जहां रूपांतरण पर दोनों प्रकार –

3

ओपी की टिप्पणी के आधार पर ("मुझे समझ नहीं आता कैसे डाले के रूप में विफल हो सकता है स्कॉट द्वारा उल्लिखित। "), असली सवाल वास्तव में कुछ ऐसा है:" dynamic_cast कैसे विफल हो सकता है? "

वह समय विफल होगा जब लक्ष्य प्रकार ऑब्जेक्ट के गतिशील प्रकार से मेल नहीं खाता है। एक साधारण उदाहरण के लिए:

struct A { 
    virtual ~A() {} 
}; 

class B : public A {}; 

int main() { 
    A *a = new A; 

    B *b = dynamic_cast<B *>(a); // should fail 
    if (b == NULL) 
     std::cout << "First cast failed.\n"; 

    A *c = new B; 
    b = dynamic_cast<B *>(c);  // should succeed 
    if (b == NULL) 
     std::cout << "Second cast failed.\n"; 
    return 0; 
} 

यहाँ हालांकि प्रकार B का एक उद्देश्य के लिए aसकता है बिंदु, यह वास्तव में बिंदु प्रकार A का एक उद्देश्य के लिए करता है। जब हम B पर इंगित करने के लिए गतिशील_कास्ट करने का प्रयास करते हैं, तो यह विफल हो जाता है। दूसरे प्रयास में, हमारे पास फिर से एक सूचक है जो न केवल कर सकता है लेकिनB के किसी ऑब्जेक्ट पर इंगित करता है। चूंकि ऐसा करता है, इस मामले में B * के लिए गतिशील_कास्ट सफल होता है।

बुनियादी स्थिति, संदर्भ मामले के लिए परिवर्तन नहीं करता है (बहुत) बस a, b और c संकेत के बजाय संदर्भ हो जाते हैं, और हम एक अपवाद को पकड़ने से विफलता ध्यान दें (@ReedCopsey पहले से ही काफी अच्छी तरह से है कि प्रदर्शन किया है जो मुझे नहीं लगता कि मेरे पास जोड़ने के लिए कुछ नया है)।

3

यहां एक पूरा उदाहरण है जो दिखाता है कि कैसे dynamic_cast एक सूचक उत्पन्न करने में विफल हो सकता है।

class A 
{ 
public: 
    virtual void Foo(); 
}; 

class B: public A 
{ 
}; 

class C: public A 
{ 
}; 

void test() 
{ 
    A a; 
    B b; 
    A* pA = &b; 
    B* pB = dynamic_cast<B*>(pA); // this works OK, returns the expected pointer 
    C* pC = dynamic_cast<C*>(pA); // this returns NULL because B isn't a C 
} 

असली दुनिया आप संकेत दिए गए कि इतने सीधी नहीं बनाया गया कास्ट करने के लिए कोशिश कर रहा हो जाएगा में, शायद वे उदाहरण के लिए एक vector से आते हैं।

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