c++ - (Int) x के बजाय static_cast<int>(x) का उपयोग क्यों करें?




casting (6)

मैंने सुना है कि static_cast फ़ंक्शन को सी-स्टाइल या सरल फ़ंक्शन-स्टाइल कास्टिंग के लिए प्राथमिकता दी जानी चाहिए। क्या ये सच है? क्यूं कर?


संक्षेप में :

  1. static_cast<>() आपको एक संकलन समय की जांच क्षमता देता है, सी-स्टाइल कास्ट नहीं करता है।
  2. static_cast<>() को C ++ स्रोत कोड के अंदर कहीं भी आसानी से देखा जा सकता है; इसके विपरीत, सी_Style कास्ट स्पॉट करने के लिए मुश्किल है।
  3. सी ++ कास्ट का उपयोग करके इरादों को बेहतर तरीके से व्यक्त किया जाता है।

अधिक स्पष्टीकरण :

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

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

चूंकि यह 4-बाइट पॉइंटर आवंटित स्मृति के 1 बाइट को इंगित करता है, इस पॉइंटर को लिखने से या तो रन-टाइम त्रुटि हो जाएगी या कुछ आसन्न स्मृति को ओवरराइट कर दिया जाएगा।

*p = 5; // run-time error: stack corruption

सी-स्टाइल कास्ट के विपरीत, स्थैतिक कलाकार संकलक को यह जांचने की अनुमति देगा कि पॉइंटर और पॉइंट डेटा प्रकार संगत हैं, जो प्रोग्रामर को संकलन के दौरान इस गलत सूचक असाइनमेंट को पकड़ने की अनुमति देता है।

int *q = static_cast<int*>(&c); // compile-time error

इस पर और पढ़ें:
Static_cast <> और सी शैली कास्टिंग के बीच क्या अंतर है
तथा
नियमित कलाकार बनाम static_cast बनाम गतिशील_कास्ट


  1. Grep या इसी तरह के टूल का उपयोग करके आपके कोड में आसानी से पाए जाने वाले कोस्ट को अनुमति देता है।
  2. यह स्पष्ट करता है कि आप किस प्रकार का कलाकार कर रहे हैं, और इसे लागू करने में संकलक की सहायता को शामिल करते हैं। यदि आप केवल कॉन्स्टेस को दूर करना चाहते हैं, तो आप const_cast का उपयोग कर सकते हैं, जो आपको अन्य प्रकार के रूपांतरण करने की अनुमति नहीं देगा।
  3. कास्ट स्वाभाविक रूप से बदसूरत हैं - आप एक प्रोग्रामर के रूप में ओवरराल कर रहे हैं कि संकलक सामान्य रूप से आपके कोड का इलाज कैसे करेगा। आप कंपाइलर से कह रहे हैं, "मैं आपसे बेहतर जानता हूं।" यह मामला है, यह समझ में आता है कि एक कलाकार का प्रदर्शन करना एक मामूली दर्दनाक चीज होना चाहिए, और उन्हें आपके कोड में रहना चाहिए, क्योंकि वे समस्याओं का संभावित स्रोत हैं।

प्रभावी सी ++ परिचय देखें


एक व्यावहारिक युक्ति: यदि आप परियोजना को व्यवस्थित करने की योजना बना रहे हैं तो आप अपने स्रोत कोड में static_cast कीवर्ड के लिए आसानी से खोज सकते हैं।


कोड के ब्लॉक में सी स्टाइल कास्ट याद करना आसान है। सी ++ स्टाइल कास्ट न केवल बेहतर अभ्यास है; वे लचीलापन की एक बड़ी डिग्री प्रदान करते हैं।

reinterpret_cast पॉइंटर प्रकार रूपांतरणों के अभिन्न अंग की अनुमति देता है, हालांकि दुरुपयोग होने पर असुरक्षित हो सकता है।

static_cast संख्यात्मक प्रकारों के लिए अच्छा रूपांतरण प्रदान करता है जैसे कि इंट्स या इनट्स को फ्लोट या किसी भी प्रकार के डेटा से टाइप करने के लिए आप विश्वास करते हैं। यह किसी भी रन टाइम चेक नहीं करता है।

दूसरी तरफ गतिशील_कास्ट इन चेकों को किसी भी संदिग्ध असाइनमेंट या रूपांतरणों को ध्वजांकित करेगा। यह केवल पॉइंटर्स और संदर्भों पर काम करता है और एक ओवरहेड लेता है।

कुछ अन्य हैं लेकिन ये मुख्य हैं जिन्हें आप पार करेंगे।


मुख्य कारण यह है कि क्लासिक सी कास्ट हम static_cast<>() , reinterpret_cast<>() , const_cast<>() , और dynamic_cast<>() बीच कोई भेद नहीं करते हैं। ये चार चीजें पूरी तरह से अलग हैं।

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

दूसरी तरफ एक reinterpret_cast<>() (या एक const_cast<>() ) हमेशा खतरनाक होता है। आप संकलक को बताते हैं: "मेरा विश्वास करो: मुझे पता है कि यह एक foo जैसा दिखता नहीं है (ऐसा लगता है कि यह व्यवहार्य नहीं है), लेकिन यह है"।

पहली समस्या यह है कि यह बताने में लगभग असंभव है कि सी-स्टाइल कास्ट में कौन सा होगा, बिना किसी बड़े और बिना कोड के टुकड़े फैलाने और सभी नियमों को जानने के बिना।

आइए इन्हें मानें:

class CMyClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

अब, इन दोनों को एक ही तरीके से संकलित किया गया है:

CMyClass *pMyObject;
pMyObject = static_cast<CMyClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CMyClass*)(pSomething); // Same as static_cast<>
                                     // Safe; as long as we checked
                                     // but harder to read

हालांकि, आइए इसे लगभग समान कोड देखें:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                  // Same as reinterpret_cast<>
                                                  // and it's wrong!!!

जैसा कि आप देख सकते हैं, इसमें शामिल सभी वर्गों के बारे में बहुत कुछ जानने के बिना दोनों स्थितियों के बीच अंतर करने का कोई आसान तरीका नहीं है।

दूसरी समस्या यह है कि सी-स्टाइल कास्ट ढूंढने में बहुत मुश्किल है। जटिल अभिव्यक्तियों में सी-स्टाइल कास्ट देखना बहुत कठिन हो सकता है। एक स्वचालित उपकरण लिखना लगभग असंभव है जिसे सी-स्टाइल कास्ट (उदाहरण के लिए एक खोज उपकरण) को पूरी तरह से उड़ाए गए सी ++ कंपाइलर फ्रंट-एंड के बिना ढूंढने की आवश्यकता होती है। दूसरी तरफ, "static_cast <" या "reinterpret_cast <" खोजना आसान है।

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
      // No compiler error.
      // but the presence of a reinterpret_cast<> is 
      // like a Siren with Red Flashing Lights in your code.
      // The mere typing of it should cause you to feel VERY uncomfortable.

इसका मतलब है कि, न केवल सी-शैली अधिक खतरनाक है, लेकिन यह सुनिश्चित करने के लिए कि वे सही हैं, उन्हें ढूंढना बहुत मुश्किल है।


यह इस बारे में है कि आप कितनी प्रकार की सुरक्षा लागू करना चाहते हैं।

जब आप लिखते हैं (bar) foo (जो reinterpret_cast<bar> foo समतुल्य है, यदि आपने एक प्रकार का रूपांतरण ऑपरेटर प्रदान नहीं किया है) तो आप कंपाइलर को प्रकार की सुरक्षा को अनदेखा करने के लिए कह रहे हैं, और जैसा कि बताया गया है।

जब आप static_cast<bar> foo लिखते हैं तो आप कम से कम यह जांचने के लिए कंपाइलर से पूछ रहे हैं कि प्रकार रूपांतरण रूपांतरण समझता है और, अभिन्न प्रकारों के लिए, कुछ रूपांतरण कोड डालने के लिए।

2014-02-26 संपादित करें

मैंने 5 साल पहले यह जवाब लिखा था, और मुझे यह गलत लगा। (टिप्पणियां देखें।) लेकिन यह अभी भी ऊपर उठता है!





casting