परिचय: C++ टाइप कास्टिंग की गलतियों को क्यों माफ नहीं करता?
\n\nनमस्ते दोस्त! यदि आपने कभी C++ में लिखा है - तो आपने निश्चित रूप से ऐसी स्थिति का सामना किया होगा जहाँ कंपाइलर टाइप बेमेल पर त्रुटि देता है। और तब आप शायद पुराने अच्छे C-style cast को याद करते हैं: (int)x। क्या यह काम करता है? हाँ। क्या यह सुरक्षित है? नहीं। क्या यह पेशेवर है? और भी कम।
C++ में चार अंतर्निहित कास्टिंग ऑपरेटर हैं, और प्रत्येक अपना कार्य हल करता है: static_cast, dynamic_cast, const_cast और reinterpret_cast। इनका सही उपयोग करने का मतलब है ऐसा कोड लिखना जो न केवल काम करे बल्कि अन्य डेवलपर्स के लिए भी समझने योग्य हो। और साथ ही - रनटाइम में रहस्यमय त्रुटियों के साथ क्रैश न हो।
\n\nइस ट्यूटोरियल में, हम वास्तविक उदाहरणों के साथ प्रत्येक कास्ट को समझेंगे, जानेंगे कि कब किसका उपयोग करना है, और कब बिल्कुल भी कास्ट न करना बेहतर है। चलिए शुरू करते हैं!
\n\nstatic_cast: सामान्य रूपांतरणों के लिए आपका विश्वसनीय मित्र
\n\nstatic_cast सबसे लोकप्रिय और सुरक्षित कास्ट है। इसका उपयोग संबंधित प्रकारों के बीच स्पष्ट रूपांतरण के लिए किया जाता है: संख्यात्मक प्रकार, इनहेरिटेंस पदानुक्रम में ऊपर/नीचे पॉइंटर्स (रनटाइम जाँच के बिना), एनुम को पूर्णांक में और इसके विपरीत।
\n\nstatic_cast का उपयोग कब करें?
\n- \n
intकोdoubleमें बदलना (और इसके विपरीत)। \n - एक ही क्लास पदानुक्रम के भीतर पॉइंटर्स को बदलना (upcast - सुरक्षित, downcast - सुनिश्चित होना आवश्यक)। \n
void*को किसी विशिष्ट प्रकार में बदलना। \n - स्पष्ट कंस्ट्रक्टर या रूपांतरण ऑपरेटरों को कॉल करना। \n
उदाहरण:
\ndouble pi = 3.14159;\nint approx = static_cast<int>(pi); // 3\n\nclass Base { public: virtual ~Base() = default; };\nclass Derived : public Base { public: void foo() {} };\n\nBase* b = new Derived;\nDerived* d = static_cast<Derived*>(b); // ठीक है, लेकिन बिना जाँच के\nd->foo();\ndelete b;\n\nमहत्वपूर्ण: static_cast रनटाइम में टाइप की जाँच नहीं करता। यदि आप सुनिश्चित हैं कि ऑब्जेक्ट वास्तव में उसी प्रकार का है - तो इसका उपयोग करें। यदि नहीं - तो dynamic_cast देखें।
\n\ndynamic_cast: जाँच के साथ सुरक्षित downcast
\n\ndynamic_cast एकमात्र कास्ट है जो केवल पॉलीमॉर्फिक क्लासेस के साथ काम करता है (कम से कम एक वर्चुअल फंक्शन होना चाहिए)। यह रनटाइम में जाँच करता है कि क्या पॉइंटर/रेफरेंस को सुरक्षित रूप से कास्ट किया जा सकता है। यदि नहीं - तो यह nullptr लौटाता है (पॉइंटर्स के लिए) या std::bad_cast फेंकता है (रेफरेंस के लिए)।
dynamic_cast का उपयोग कब करें?
\n- \n
- जब आप सुनिश्चित नहीं हैं कि ऑब्जेक्ट वास्तव में व्युत्पन्न प्रकार का है। \n
- विषम कंटेनरों के साथ काम करते समय (उदाहरण के लिए, Base* का vector)। \n
- डिज़ाइन पैटर्न में (उदाहरण के लिए, Visitor)। \n
उदाहरण:
\nclass Base { public: virtual ~Base() = default; };\nclass Derived : public Base { public: void specific() {} };\nclass Other : public Base {};\n\nvector<Base*> objects = {new Derived, new Other, new Derived};\n\nfor (Base* obj : objects) {\n Derived* d = dynamic_cast<Derived*>(obj);\n if (d) {\n d->specific(); // केवल Derived के लिए सुरक्षित\n }\n}\n\nनुकसान: dynamic_cast static_cast से धीमा है, क्योंकि इसे RTTI (Run-Time Type Information) की आवश्यकता होती है। प्रदर्शन-महत्वपूर्ण भागों में इसका दुरुपयोग न करें।
\n\nconst_cast: जब कॉन्स्टैंटनेस हटानी हो (लेकिन सावधानी से!)
\n\nconst_cast एकमात्र कास्ट है जो cv-क्वालिफायर (const, volatile) को हटा (या जोड़) सकता है। यह अच्छा लगता है, लेकिन व्यवहार में इसका उपयोग शायद ही कभी और केवल चरम मामलों में किया जाता है।
इसकी आवश्यकता क्यों है? कभी-कभी आपको किसी ऑब्जेक्ट का कॉन्स्टैंट रेफरेंस मिलता है, लेकिन आपको एक पुराने फंक्शन को कॉल करने की आवश्यकता होती है जो const के रूप में चिह्नित नहीं है, भले ही वह ऑब्जेक्ट को नहीं बदलता। या C लाइब्रेरीज़ के साथ काम करते समय।
उदाहरण (सही):
\nvoid printInt(const int* p) {\n // पुराना