2013-08-26 12 views
9

कुछ the use of dynamic_cast often means bad design and dynamic_cast can be replaced by virtual functionsगतिशील_कास्ट बुरा क्यों है या नहीं? क्या मुझे इस मामले में गतिशील_कास्ट का उपयोग करना चाहिए?

  1. क्यों dynamic_cast के उपयोग पर विचार कर रहा है बुरा डिजाइन कहते हैं?
  2. मान लीजिए मैं मैं नाम func(Animal* animal, int animalType) ढंग से काम किया है, समारोह में कार्यान्वयन की तरह है:

    bool func(Animal* animal, int animalType) 
    { 
        ... 
        /* Animal is the base class of Bear, Panda, Fish .... 
        dynamic_cast animal to real animals(Bear, Panda, Fish...) 
        according to animalType. Do some processing with this specific 
        type of animal, using its additional information beyond base 
        class Animal. */ 
    } 
    

इस मामले dynamic_cast के समुचित उपयोग है?

+0

' dynamic_cast' "बुरा" है क्योंकि यह धीमा/ओवरकिल है। इसके अलावा, उस टूल का उपयोग करें जो आपकी समस्या हल करता है। कहानी का अंत। – Mehrdad

+0

गतिशील बहुरूपता और विशेष रूप से आभासी कार्यों का पूरा बिंदु यह है कि आपको * सटीक * प्रकार की देखभाल करने की आवश्यकता नहीं है, लेकिन केवल यह जानना है कि यह * कुछ प्रकार * बेस प्रकार * है जो एक प्रदान करता है कुछ इंटरफ़ेस, हालांकि इसे विशेष * व्युत्पन्न प्रकार * द्वारा कार्यान्वित किया जा सकता है। 'dynamic_cast' सरल कारण के लिए" खराब डिज़ाइन "है कि यह इस उद्देश्य का उल्लंघन करता है, क्योंकि आपको * * ऑब्जेक्ट को * * व्युत्पन्न प्रकार * होने की आवश्यकता है, इसलिए इसे * बेस प्रकार * जानने के लिए पर्याप्त नहीं है। ऐसा कहा जा रहा है कि इसका अभी भी इसका उपयोग है (विशेष रूप से दुनिया जितनी सरल नहीं है * जावा * इसे पसंद करती है)। –

उत्तर

14

यह dynamic_cast का उपयोग करने के लिए बिल्कुल गलत जगह है। आपको बहुरूपता का उपयोग करना चाहिए। Animal कक्षाओं में से प्रत्येक को virtual फ़ंक्शन होना चाहिए, कहें, process और यहां आपको केवल animal->process() पर कॉल करना चाहिए।

class Animal{ 
    virtual void Process() = 0; 
} 
class Cat:public Animal{ 
    void Process() {cout<<" I am a tiny cat";} 
} 
class Bear :public Animal{ 
    void Process(){cout<<"I am a big bear"; 
} 

void func(Animal* animal){ 
    if(animal != NULL) animal -> Process(); 
} 

अन्य समस्याएं।

animal क्या कुत्ता है, लेकिन animal_type एक बग के कारण यह एक बिल्ली कहता है?

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

पेज। कम से कम, animal_typeAnimal का सदस्य होना चाहिए।

+0

क्या होगा यदि वह कुछ जानवरों को उड़ना चाहता है? – user1233963

+0

@ user1233963 विरासत के कई स्तर, या 'कॉन्स्ट बूल can_fly' –

+3

"विरासत के कई स्तर" और वह वापस डायनामिक_कास्ट – user1233963

0

जब आप डाउनकास्टिंग का उपयोग करते हैं, तो गतिशील_कास्ट अच्छा होता है, क्योंकि यह आपको अप्रासंगिक प्रकार के लिए डाउनकास्ट करने के लिए प्रतिबंधित करता है। कृपया this देखें।

+2

दरअसल, मुझे लगता है कि आपका मतलब * प्रासंगिक * है, यह भी ... यह एक बल्कि कच्चा जवाब है। केवल लिंक ही जवाब हैं वृद्ध क्योंकि लिंक नियमित रूप से तोड़ते हैं और फिर ... आपका जवाब बेकार होगा। इस प्रकार लिंक को * अतिरिक्त * संदर्भों के रूप में उपयोग किया जाना चाहिए, अगर आपको यह नहीं पता कि चीज को और कैसे समझाया जाए तो आप हमेशा यह बता सकते हैं कि लिंक क्या कह रहा है। –

+0

@MatthieuM। हो सकता है कि आप सही हों, लेकिन लिंक मेरे अपने लेख का है, लेकिन मुझे यहां कुछ शांति भी जोड़नी चाहिए थी। –

+0

मुझे लेख पता है, सप्ताह के अंत में reddit पर इस पर टिप्पणी की;) –

3

सिद्धांत रूप में, डाउन-कास्टिंग कभी आवश्यक नहीं होना चाहिए। इसके बजाय आपको आवश्यक कक्षा virtual विधि शामिल करने के लिए बेस क्लास को अनुकूलित करना चाहिए।

प्रैक्टिस में, आपको तीसरे पक्ष के पुस्तकालयों जैसी चीजें मिलती हैं। इस मामले में, आधार वर्ग को संशोधित करने के एक विकल्प नहीं है और इस प्रकार आप dynamic_cast का उपयोग कर के लिए मजबूर किया जा सकता है ...

अपने उदाहरण पर वापस

class Animal { 
public: 
    // starts moving toward `p`, 
    // throws a `Unreachable` exception if `p` cannot be reached at the moment. 
    virtual void moveToward(Point const& p) = 0; 
}; // class Animal 

और फिर:

bool move(Animal& animal, Point const& p) { 
    try { 
     animal.moveToward(p); 
     return true; 
    } catch (Unreachable const& e) { 
     LOG(animal.id() << " cannot reach " << p << ": " << e.what()); 
    } 

    return false; 
} // move 
+1

आपका सिद्धांत गलत है। ऐसे मामले हैं जहां डाउनकास्टिंग पसंदीदा समाधान है। (निश्चित रूप से उसका उदाहरण नहीं।) यदि आप निम्न स्तर के चैनल में डेटा ले जा रहे हैं, उदाहरण के लिए, जिसमें परिवहन चैनल को उच्च स्तरीय इंटरफेस का कोई ज्ञान नहीं है। या यहां तक ​​कि आपके पास एक कक्षा है जो कई इंटरफेस लागू करती है: 'dynamic_cast' (पॉइंटर्स के साथ) यह पूछने का मानक तरीका है कि वास्तविक वस्तु विस्तारित इंटरफ़ेस लागू करती है या नहीं। –

+1

@ जेम्सस्केज़: डाउन-कास्टिंग के साथ समस्या यह है कि आप जिस प्रकार के डाउन-कास्ट कर सकते हैं, उसका सेट संभावित रूप से असंबद्ध है। यही कारण है कि इसे आम तौर पर संदेह से मुलाकात की जाती है: जब किसी वस्तु पर 'गतिशील_कास्ट' के माध्यम से एक विशिष्ट प्रक्रिया की जाती है, तो आप यह नहीं जान सकते कि क्या अन्य प्रकार हैं जहां ऐसी प्रक्रिया भी की जानी चाहिए। –

+3

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

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