2009-09-05 12 views
5

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

उदाहरण:

#include <iostream> 
#include <typeinfo> 

using namespace std; 

class Shape { public: virtual ~Shape() {}; }; 
class Circle : public Shape {}; 
class Square : public Shape {}; 
class Other {}; 

int main() { 
    Circle c; 

    Shape* s = &c; // Upcast: normal and OK 

    // More explicit but unnecessary: 
    s = static_cast<Shape*>(&c); 
    // (Since upcasting is such a safe and common 
    // operation, the cast becomes cluttering) 

    Circle* cp = 0; 
    Square* sp = 0; 

    // Static Navigation of class hierarchies 
    // requires extra type information: 
    if(typeid(s) == typeid(cp)) // C++ RTTI 
     cp = static_cast<Circle*>(s); 
    if(typeid(s) == typeid(sp)) 
     sp = static_cast<Square*>(s); 
    if(cp != 0) 
     cout << "It's a circle!" << endl; 
    if(sp != 0) 
     cout << "It's a square!" << endl; 

    // Static navigation is ONLY an efficiency hack; 
    // dynamic_cast is always safer. However: 
    // Other* op = static_cast<Other*>(s); 
    // Conveniently gives an error message, while 
    Other* op2 = (Other*)s; 
    // does not 
} ///:~ 

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

+3

मेरी आंखें ओउ। इंडेंट? –

+0

आपके संदेश को पुस्तक के लेखक को व्यक्त करेगा। – Ankur

+0

सी-स्टाइल कास्ट '(अन्य *) एस 'अनिवार्य रूप से' reinterpret_cast 'के समान है, इस मामले में, यही कारण है कि यह चेतावनी के बिना संकलित करता है (आप अनिवार्य रूप से संकलक को चिंता न करने के बारे में बता रहे हैं, आप जानते हैं कि आप क्या जानते हैं कर रहे हैं) – Attila

उत्तर

9

static_castसे प्रति RTTI की जरूरत नहीं है - typeid करता है (dynamic_cast करता है), लेकिन यह एक पूरी तरह से अलग मुद्दा है। अधिकांश कास्ट सिर्फ कंपाइलर को बता रहे हैं "मेरा विश्वास करो, मुझे पता है कि मैं क्या कर रहा हूं" - dynamic_cast अपवाद है, यह संकलक को रनटाइम पर जांचने और संभावित रूप से विफल होने के लिए कहता है। यह वही बड़ा प्रदर्शन अंतर है!

+0

क्या आप ऊपर कार्यान्वित के रूप में dynamic_cast और static_cast के साथ कोई प्रदर्शन अंतर देखते हैं (यह टाइपिड का उपयोग करता है)। – Ankur

+4

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

+0

अपना अंक मिला। धन्यवाद। – Ankur

1

dynamic_cast यदि आप टाइपिड चेक नहीं कर चुके थे और कलाकार सफल नहीं हो पाए तो न्यूल वापस आ जाएगा। static_cast सफल होगा (और अनिश्चित व्यवहार का कारण बनता है, जैसे अंतिम क्रैश)। यह गति अंतर की संभावना है।

+3

bad_cast अपवाद फेंक दिया जाएगा हम गतिशील_कास्ट के साथ संदर्भों का उपयोग करें। सूचक परिवर्तक के साथ, गलत प्रयास के लिए NULL वापस कर दिया जाएगा। – Ankur

+0

कूल, स्पष्टीकरण के लिए धन्यवाद। मैं इसे प्रतिबिंबित करने के लिए अद्यतन करूँगा। –

7

यह अधिक बेहतर होने पर सभी प्रकार के स्विचिंग से बचने के लिए बेहतर है। यह आमतौर पर एक आभासी विधि है कि अलग ढंग से विभिन्न उप-प्रकारों के लिए लागू किया गया है के लिए प्रासंगिक कोड का स्थान बदलना द्वारा किया जाता है:

class Shape { 
public: 
    virtual ~Shape() {}; 
    virtual void announce() = 0; // And likewise redeclare in Circle and Square. 
}; 

void Circle::announce() { 
    cout << "It's a circle!" << endl; 
} 

void Square::announce() { 
    cout << "It's a square!" << endl; 
} 

// Later... 
s->announce(); 

आप एक पूर्व मौजूदा वंशानुगत पदानुक्रम है कि आप बदल नहीं सकते के साथ काम कर रहे हैं, तो Visitor pattern के लिए जांच टाइप-स्विचिंग के लिए एक अधिक विस्तार योग्य विकल्प।

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

+0

हालांकि यह सामान्य रूप से एक अच्छी सलाह है, यह उत्तर नहीं है, अंकुर की तलाश है, क्योंकि यह दोनों जानवरों के बीच अंतर की व्याख्या नहीं करता है। –

+1

मुझे लगता है कि आप सही हैं - उन्होंने मूल रूप से पूछा "मेरे पैरों पर बंदूक को इंगित करने का सबसे प्रभावी तरीका क्या है?", और मैंने मूर्खता से जवाब दिया कि "अपने पैरों पर बंदूक का लक्ष्य न रखें", जो प्रासंगिक नहीं है । :- पी –

+0

हां, फिर भी अच्छी टिप। – Ankur

5
स्थिर डाली (और typeid जांच) के साथ

आप कर सकते हैं नहीं खिन्न एक मध्यवर्ती प्रकार के (बच्चे पिता से निकला दादा से निकला है, आप नहीं पिता को दादा से खिन्न कर सकते हैं) के उपयोग में एक छोटे से अधिक सीमित है। typeid जांच के बिना static_cast कार्यक्षमता के लिए शुद्धता का त्याग है, और फिर आप जानते हैं कि वे क्या कहते हैं:

जो प्रदर्शन के लिए शुद्धता बलिदान वह हकदार न

तो जाहिर है, ऐसी परिस्थितियाँ होती हैं, जहां आप हताश जरूरत में कर रहे हैं कुछ सीपीयू निर्देशों में से और सुधारों को देखने के लिए कहीं और नहीं है और आप वास्तव में सुरक्षित हैं कि आप क्या कर रहे हैं और आपने सहन किया है (दाएं?) कि प्रदर्शन प्राप्त करने का एकमात्र स्थान गतिशील_कास्ट के बजाय static_cast का उपयोग कर रहा है ... फिर आप पता है कि आपको अपने डिज़ाइन, या अपने एल्गोरिदम को फिर से काम करना होगा या बेहतर हार्डवेयर प्राप्त करना होगा।

rtti + static_cast का उपयोग करके लगाए गए प्रतिबंध यह है कि आप बाद में कुछ व्युत्पन्न कक्षाओं के साथ अपने कोड को विस्तारित नहीं कर पाएंगे, जहां आपने कुछ सीपीयू निर्देश प्राप्त करने के लिए इस चाल का उपयोग किया है। आपके द्वारा प्राप्त किए गए CPU समय की तुलना में वह खुद को फिर से काम करने में अधिक समय लगेगा (इंजीनियरिंग समय जो अधिक महंगा है)। यदि, किसी भी दर पर, डाउनकास्ट को समर्पित समय ध्यान देने योग्य है, तो अपने डिजाइन को j_random_hacker के रूप में पुन: कार्य करें, यह डिजाइन और प्रदर्शन दोनों में सुधार करेगा।

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