2012-02-04 17 views
9

At a reply of a blog post of Raymond Chen,reinterpret_cast के बजाय static_cast का उपयोग करना क्यों महत्वपूर्ण है?

एक प्रश्नकर्ता

रेमंड ने कहा, मेरा मानना ​​है कि जब से व्युत्पन्न वर्ग में आधार वर्ग subobject की स्थिति अनिर्दिष्ट है आईएसओ सी ++ 2003 मानक के अनुसार सी ++ उदाहरण सही नहीं है (10-3, पेज 168), और आप मानते हैं कि बेस क्लास सबोबजेक्ट हमेशा शुरुआत में होता है। सी उदाहरण सी ++ में भी ठीक होगा, इसलिए मैं इसके साथ रहूंगा।

रेमंड ने कहा

[कोड इस धारणा नहीं है। यही कारण है कि reinterpret_cast के बजाय static_cast का उपयोग करना महत्वपूर्ण है। इसे आज़माएं: वर्चुअल विधि को ओवरराप्पेड में जोड़ें (इसलिए एक vtable सामने आता है) और देखें कि कंपाइलर क्या करता है। -रेमंड]

मैं उनकी टिप्पणियों को पढ़ने के बाद अनुमान लगा सकता हूं। Static_cast का उपयोग उदाहरण पर ठीक है लेकिन reinterpret_cast नहीं है। क्योंकि reinterpret_cast vtable को परिवर्तित नहीं करता है। क्या मैं इसे सही समझता हूँ?
हालांकि, अगर मैं वहां सी-स्टाइल कास्ट का उपयोग करता हूं (reinterpret_cast नहीं), तो क्या यह गलत भी हो सकता है?

मैं इसे समझने के लिए अधिक प्रभावी सी ++ के कास्ट स्पष्टीकरण को फिर से पढ़ता हूं। लेकिन इसके बारे में कोई जवाब नहीं था।

+2

मुझे सी ++ में बिल्कुल भी पता नहीं है, लेकिन मेरी समझ यह है कि "कास्ट दोबारा परिभाषित करें" का अर्थ है कि * * (destination_type *) और 'सी में मतलब होगा। संभवतः" स्थैतिक कलाकार "वास्तव में कक्षा संबंधों को लेता है खाता और संकलक को गैर-तुच्छ रूपांतरण कार्य करने की अनुमति देता है। –

उत्तर

17

static_cast का उपयोग उदाहरण पर ठीक है लेकिन reinterpret_cast नहीं है। क्योंकि reinterpret_cast vtable को परिवर्तित नहीं करता है।

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

आइए नाटक हमारे कार्यान्वयन बाहर देता है काल्पनिक OVERLAPPEDEX वर्ग इस तरह एक आभासी समारोह है:

+------+------------+------------------+-------------+ 
| vptr | OVERLAPPED | AssociatedClient | ClientState | 
+------+------------+------------------+-------------+ 
    ^
     | 
     ptr 

सूचक हम OVERLAPPED subobject के लिए अंक दिया जाता है। reinterpret_cast उसमें बदलाव नहीं करेगा। यह केवल प्रकार बदल जाएगा। जाहिर है, इस पते के माध्यम से OVERLAPPEDEX वर्ग तक पहुंच आसानी से विनाश को खत्म कर देगी, क्योंकि इसके सबबजेक्ट्स के स्थान अब सब गलत हैं!

 what we believe we have when we access OVERLAPPEDEX through the pointer 
     +------+------------+------------------+-------------+ 
     | vptr | OVERLAPPED | AssociatedClient | ClientState | 
+------+------+-----+------+-----------+------+------+------+ 
| vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have 
+------+------------+------------------+-------------+ 
    ^
     | 
     ptr 

static_cast कि एक OVERLAPPED*OVERLAPPEDEX* कन्वर्ट करने के लिए यह पता समायोजित करना चाहिए जानता है, और सही काम करता है:

+------+------------+------------------+-------------+ 
| vptr | OVERLAPPED | AssociatedClient | ClientState | 
+------+------------+------------------+-------------+ 
^ 
| 
ptr after static_cast 

हालांकि, अगर मैं का उपयोग सी-शैली वहां पर डालें (reinterpret_cast नहीं), क्या यह भी गलत हो सकता है?

एक सी शैली डाली निम्नलिखित वह सफल होता है के पहले एक के रूप में परिभाषित किया गया है:

  1. const_cast
  2. static_cast
  3. static_cast, तो const_cast
  4. reinterpret_cast
  5. reinterpret_cast, फिर const_cast

आप देख सकते हैं, एक static_castreinterpret_cast से पहले की कोशिश की है, इसलिए इस मामले में, एक सी शैली डाली भी सही काम करना होगा।


More info


गारंटी नहीं। reinterpret_cast पर क्या होता है इसके बारे में बहुत कम गारंटी है। मेरे द्वारा किए जाने वाले सभी कार्यान्वयनों को केवल उसी पते को अपरिवर्तित किया जाएगा।

+0

हां, मेरा 'परिवर्तित vtable' बहुत अजीब वाक्य था। बीटीडब्ल्यू, क्या सी-स्टाइल कोस्टर भी विरासत-रिश्ते को जानता है? शायद यह नहीं है। लेकिन मैंने हमेशा सी-स्टाइल कास्ट किया है, भले ही मैं सी ++ का उपयोग करता हूं। और मुझे लगता है कि यह उदाहरण में भी अच्छा काम करता है। यह अजीब चीज है। – Benjamin

+1

@ बेंजामिन I ने सी-स्टाइल कास्ट के बारे में एक स्पष्टीकरण जोड़ा, और यह इस मामले में क्यों काम करता है। हालांकि मैं उनका उपयोग करने के खिलाफ सिफारिश करता हूं, क्योंकि यह हमेशा स्पष्ट नहीं होता कि कौन से विकल्पों को चुना जाता है। एक सी-शैली का मामला एक बहुत ही बदमाश हथौड़ा है। –

+0

बेशक मैं आपकी सिफारिश का पालन करूंगा, क्योंकि अब मैं इसे समझता हूं। धन्यवाद। क्या सी-स्टाइल कैस्टर करने का आपका क्रम मानकीकृत है, यद्यपि? – Benjamin

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