2015-11-08 10 views
11

इस उदाहरण पर विचार, जहां आधार वर्ग कुछ डेटा सदस्य हैं, जबकि ली गई एक ही एक अतिरिक्त तरीका प्रदान करता है:क्या यह डाउनकास्टिंग अपरिभाषित है?

struct TestBase 
{ 
    int x; 
    TestBase() : x(5) {} 
}; 

struct TestDerived : public TestBase 
{ 
    void myMethod() 
    { 
     x=8; 
    } 
}; 

int main() 
{ 
    TestBase b; 
    TestDerived& d=static_cast<TestDerived&>(b); 
    d.myMethod(); 
} 

यह गलत प्रकार के downcasting है, इसलिए AFAIU यह व्यवहार अपरिभाषित है। लेकिन क्या ऐसे मामलों में शायद कुछ अपवाद हैं, जहां व्युत्पन्न वर्ग का लेआउट बेस क्लास के समान है? यदि आप असंगत प्रकार के बीच कास्ट करने के लिए प्रयास

+0

'टेस्टडेरिव'/'टेस्टबेस' एक मानक लेआउट प्रकार है, जिससे बहुत अच्छी गारंटी मिलनी चाहिए कि यह काम करेगा। हालांकि, यह कानूनी है या नहीं, इस सवाल का जवाब नहीं देता है। – MicroVirus

+0

शायद यह प्रश्न का उत्तर देता है: [दो समान वर्गों के पॉइंटर्स के बीच कास्टिंग की सुरक्षा?] (Http://stackoverflow.com/questions/7762929/safety-of-casting-between-pointers-of-two-identical-classes) – MicroVirus

+0

या शायद यहां: [लगभग पॉड डेटा के लिए reinterpret_cast (लेआउट-संगतता पर्याप्त है)] (http://stackoverflow.com/questions/5060879/reinterpret-cast-for-almost-pod-data-is-layout-compatibility- पर्याप्त) – MicroVirus

उत्तर

8
मानक से

(जोर मेरा):

§5.2.9 स्टेटिक डाली [expr.static.cast] ...

(2) प्रकार का एक lvalue "CV1 बी," जहां बी एक वर्ग प्रकार है, टाइप करने के लिए डाली जा सकती है, "CV2 डी के संदर्भ में," जहां डी एक वर्ग, बी से प्राप्त करता है, तो एक वैध मानक रूपांतरण से है "पॉइंटर टू डी" से "पॉइंटर टू बी" मौजूद है, सीवी 2है, सीवी 1, और बी की तुलना में अधिक सीवी-योग्यता, या तो डी का वर्चुअल बेस क्लास नहीं है और न ही वर्चुअल बेस डी की कक्षा का मूल वर्ग है। परिणाम में "सीवी 2 डी" है। प्रकार का एक xvalue प्रकार के "सीवी 1 बी" के रूप में एक ही बाधा के साथ "सीवी 2 डी" के लिए "समानता संदर्भ" टाइप करने के लिए हो सकता है यदि वास्तव में "सीवी 1 बी" प्रकार की वस्तु वास्तव में है प्रकार डी के किसी ऑब्जेक्ट का उप-स्रोत, परिणाम डी की संलग्न वस्तु को संदर्भित करता है अन्यथा, व्यवहार अपरिभाषित है।

मेरा पहला अनुमान था कि कलाकारों इस मामले में मान्य होना चाहिए क्योंकि मैं अवधि subobject से उलझन में हो गया।

अब (@ टीसी और @ एमएम के लिए धन्यवाद), यह स्पष्ट है कि इस मामले में व्यवहार को अपरिभाषित किया गया है।

डाली निम्न उदाहरण में मान्य होगा:

int main() 
{ 
    TestDerived d; 
    TestBase &br = d; // reference to a subobject of d 
    TestDerived &dr = static_cast<TestDerived&>(br); // reference to the original d object 
    d.myMethod(); 
} 

यहाँ, वर्ग TestDerived (d) की एक वस्तु वर्ग TestBase की एक subobject (br इस वस्तु के लिए एक संदर्भ है) होगा।

+2

"बी" वास्तव में टेस्टडिएव के प्रकार की ऑब्जेक्ट का उप-योग कैसे है? –

+1

बोल्ड किए गए पाठ से पता चलता है कि उदाहरण * मान्य नहीं है –

-1

static_cast<> एक संकलक त्रुटि उत्पन्न होगा, लेकिन यह संकलन समय या क्रम कि डाली मान्य है में कोई आश्वासन बनाता है।

के बाद से TestDerived TestBase से विरासत, यह एक कानूनी कलाकारों के रूप में static_cast ऑपरेटर द्वारा अनुमति दी है, लेकिन सभी downcasts जरूरी सुरक्षित डाले हैं।

उपरोक्त कोड में, यह सिर्फ होता है सुरक्षित रूप से काम करने के लिए - सबसे अधिक संभावना है क्योंकि TestMethod केवल आधार वर्ग के सदस्यों तक पहुँचता है, एकल विरासत, कोई vtables, और कुछ भी जटिल नहीं कर रही है। इस प्रकार, कंपाइलर कास्ट को नो-ऑप सरल उदाहरण के रूप में पेश करता है। अन्य आपको बताएंगे कि "यह अनिर्धारित व्यवहार है" - और इस तरह लिखे गए कोड के बारे में कुछ भी नहीं मानना। (और वे भी सही होगा।)

+2

वैसे यहां 'dynamic_cast' काम नहीं करेगा क्योंकि' टेस्टबेस 'पॉलिमॉर्फिक नहीं है । – Ruslan

+0

@Ruslan - निश्चित – selbie

+2

यह गलत है, कास्ट स्वयं अनिर्धारित व्यवहार का कारण बनता है (सर्गेज के उत्तर में बोल्ड टेक्स्ट देखें) –

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