2010-10-11 13 views
9
#include <iostream> 
using namespace std; 
class X{ 
    public: 
    virtual void f(){} 
}; 

class Y { 
    public: 
    virtual void g() {} 
}; 

int main() 
{ 
    X * x = new X(); 
    Y* y = dynamic_cast<Y*>(x); //A 
    // Y* y = static_cast<Y*>(x); //B 
    cout << y << endl; 
} 

A पर काम कर रहा कास्ट संकलित जबकि B नहीं करता है। मुझे समझ में क्यों B संकलित नहीं प्राप्त करता है लेकिन क्यों A हालांकि X संकलित हो जाता है और Y पूरी तरह से असंबंधित प्रकार के होते हैं?गतिशील असंबंधित प्रकार

उत्तर

1

संकलक परवाह नहीं है, क्योंकि यह dynamic_cast है। कास्ट के बाद yNULL होगा।

5

गतिशील कास्ट रनटाइम प्रकार की जानकारी का उपयोग करता है। तो यह कानूनी है इस मामले में लेकिन यह एक शून्य सूचक वापस आ जाएगा। स्थिर कास्ट संकलक द्वारा मूल्यांकन किया जाता है।

1

dynamic_cast आरटीटीआई का उपयोग करते हुए रनटाइम पर प्रकार की जांच करता है, जबकि static_cast संकलन समय पर इसे निष्पादित करता है। तो अगर आप A चलाते हैं तो आपको क्या मिलेगा y == NULL होगा।

मैं तुम्हें read up सी पर सुझाव है ++ प्रकार डाले। ,

http://www.cplusplus.com/doc/tutorial/typecasting/

dynamic_cast

1

गतिशील डाली NULL भेजता है अगर यह डाली पूरा नहीं कर सकते और वह प्रकार तर्क वस्तु का वास्तविक प्रकार नहीं है, तो कास्ट का परिणाम NULL होगा।

Y* y = dynamic_cast<Y*>(x); // NULL because `X` is not a `Y` 
1

की खोज करते हैं [गतिशील कलाकारों का उपयोग करके] क्या आप एक सूचक प्रकार के कास्ट करने के लिए प्रयास करते हैं और:

20

यही कारण है कि dynamic_cast असंबंधित प्रकार के बीच की अनुमति दी जाती है:

class X{ 
    public: 
    virtual void f(){} 
}; 

class Y { 
    public: 
    virtual void g() {} 
}; 

class Z : public X, public Y {}; 

int main() 
{ 
    X* x = new Z(); 
    Y* y = dynamic_cast<Y*>(x); // compiles and yields non-null pointer 
} 
1

static_cast और dynamic_cast में बहुत बड़ा अंतर नहीं है, मैं सिर्फ वस्तुओं दुनिया के लिए चर्चा कम कर देंगे।

एक static_cast ऊपर डाली (कुख्यात) के लिए इस्तेमाल किया जा सकता है। यही कारण है:

void foo(Base& b) { Derived& d = static_cast<Derived&>(b); } 

संकलक, आकलन कर सकते हैं कि क्या यह कानूनी है या नहीं क्योंकि Derived यह की परिभाषा होने जानता है या नहीं, Derived वास्तव में Base के वंशज है।

गैर तुच्छ पदानुक्रम के लिए:

struct Base {}; 
struct D1: Base {}; 
struct D2: Base {}; 
struct Derived: D1, D2 {}; 

यह एक त्रुटि प्राप्त होते हैं: संकलक पता नहीं अड्डों (D1 से एक या D2 से एक आप से आया है) के रूप से।

या यदि आप virtual विरासत का प्रयोग किया:

struct VDerived: virtual VBase {}; 

संकलक होगा रन-टाइम जानकारी, और इस प्रकार संकलन की जरूरत भी विफल हो जाएगा।

dynamic_cast हालांकि अधिक चालाक है, हालांकि यह रनटाइम-ओवरहेड की लागत पर आता है। संकलक वस्तुओं के बारे में जानकारी उत्पन्न करता है आम तौर पर RTTI (क्रम प्रकार सूचना) के रूप में जानते हैं, कि dynamic_cast अनुमति देने के लिए पता लगाने जाएगा:

// will throw `bad_cast` if b is not a `Derived` 
void foo(Base& b) { Derived& d = dynamic_cast<Derived&>(b); } 

शाखाओं करवाते हैं कास्ट:

कास्ट सच क्रम प्रकार के आधार पर

struct X {}; 
struct Y {}; 

void foo(X* x) { Y* y = dynamic_cast<Y*>(x); } 

// If I add: 
struct Z: X, Y {}; 

// then if x is in fact a Z, y will be non-null 

वर्चुअल विरासत में शामिल होने पर कास्ट करें। void* को

void bar(VBase* vb) { VDerived* vd = dynamic_cast<VDerived*>(vb); } 

कास्ट (यह कुछ हद तक खास है) वस्तु का सच पता मिलता है।

void foobar(X* x) 
{ 
    void* xAddr = dynamic_cast<void*>(x); 

    Y* y = dynamic_cast<Y*>(y); 
    void* yAddr = dynamic_cast<void*>(y); 

    Z* z = dynamic_cast<Z*>(x); 
    void* zAddr = dynamic_cast<void*>(z); 
    if (z) { assert(xAddr == yAddr && xAddr == zAddr); } 
} 

नोट अगर वहाँ पदानुक्रम की वजह से एक अस्पष्टता है कि यह अभी भी काम नहीं करता है (ऊपर D1/D2 उदाहरण में है)।

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