परिचय: शुरुआती के लिए पैरेंट कंस्ट्रक्टर क्यों एक माइनफील्ड है
\n\nहर कोई जिसने C++ में इनहेरिटेंस सीखना शुरू किया, देर-सबेर ऐसी स्थिति का सामना करता है: आप एक चाइल्ड क्लास बनाते हैं, कंपाइलर त्रुटि देता है, प्रोग्राम बिल्ड नहीं होता, और आप समझ नहीं पाते — क्यों? अक्सर समस्या की जड़ बेस क्लास कंस्ट्रक्टर के गलत कॉल में होती है। Stack Overflow पर इस प्रश्न के हज़ारों व्यूज़ हैं, और यह उचित भी है: अनुभवी डेवलपर्स भी कभी-कभी बुनियादी नियम भूल जाते हैं।
\n\nइस लेख में हम C++ में बेस क्लास कंस्ट्रक्टर को कॉल करने के नियमों को समझेंगे, शीर्ष-5 सबसे सामान्य गलतियों पर चर्चा करेंगे और दिखाएंगे कि उनसे कैसे बचा जाए। यदि आप बिना किसी आश्चर्य के विश्वसनीय कोड लिखना चाहते हैं — अंत तक पढ़ें।
\n\nसंक्षिप्त परिचय: इनहेरिटेंस में कंस्ट्रक्टर कैसे काम करते हैं
\n\nC++ में कंस्ट्रक्टर इनहेरिट नहीं होते हैं। जब आप डिराइव्ड क्लास का ऑब्जेक्ट बनाते हैं, तो पहले बेस क्लास का कंस्ट्रक्टर (अप्रत्यक्ष या स्पष्ट रूप से) कॉल होता है, और फिर चाइल्ड का कंस्ट्रक्टर। यदि आप यह निर्दिष्ट नहीं करते कि कौन सा पैरेंट कंस्ट्रक्टर कॉल करना है, तो कंपाइलर बेस क्लास के डिफ़ॉल्ट कंस्ट्रक्टर को कॉल करने का प्रयास करेगा। यदि वह मौजूद नहीं है — तो आपको कंपाइलेशन त्रुटि मिलेगी।
\n\nस्पष्ट कॉल इनिशियलाइज़ेशन लिस्ट के माध्यम से किया जाता है:
\n\nclass Base {\npublic:\n Base(int x) { /* ... */ }\n};\n\nclass Derived : public Base {\npublic:\n // सही: Base(int) का स्पष्ट कॉल\n Derived() : Base(42) { /* ... */ }\n};\n\nसरल लगता है? लेकिन यहीं पर शुरुआती 90% गलतियाँ करते हैं। आइए उन्हें क्रम से समझें।
\n\nबेस क्लास कंस्ट्रक्टर को कॉल करने में शीर्ष-5 गलतियाँ
\n\nगलती #1: पैरामीटर के साथ पैरेंट कंस्ट्रक्टर को कॉल करना भूल गए
\n\nसबसे आम समस्या। यदि बेस क्लास में डिफ़ॉल्ट कंस्ट्रक्टर नहीं है, और आपने इसे स्पष्ट रूप से कॉल नहीं किया — तो कंपाइलर त्रुटि देगा।
\n\nclass Base {\npublic:\n Base(int x) { /* इनिशियलाइज़ेशन */ }\n};\n\nclass Derived : public Base {\npublic:\n // त्रुटि: कंपाइलर Base() को कॉल करने का प्रयास करता है, जो मौजूद नहीं है\n Derived() { }\n};\n\nकैसे ठीक करें:
\n\nclass Derived : public Base {\npublic:\n // सही: स्पष्ट रूप से Base(int) को कॉल करें\n Derived() : Base(0) { }\n // या बाहर से पैरामीटर पास करें:\n Derived(int x) : Base(x) { }\n};\n\nगलती #2: गलत इनिशियलाइज़ेशन क्रम
\n\nकई लोग सोचते हैं कि इनिशियलाइज़ेशन लिस्ट में कंस्ट्रक्टर कॉल का क्रम निष्पादन का क्रम निर्धारित करता है। ऐसा नहीं है। बेस क्लास हमेशा पहले इनिशियलाइज़ होता है, भले ही आपने उसका कॉल कहीं भी लिखा हो।
\n\nclass Derived : public Base {\nprivate:\n int value;\npublic:\n // ऐसा लगता है कि value पहले इनिशियलाइज़ होगा? नहीं!\n Derived() : value(10), Base(5) { }\n // वास्तव में: पहले Base(5), फिर value(10)\n};\n\nयह तार्किक त्रुटियों का कारण बन सकता है यदि value का इनिशियलाइज़ेशन बेस क्लास की स्थिति पर निर्भर करता है।
गलती #3: कंस्ट्रक्टर के बॉडी में पैरेंट कंस्ट्रक्टर को कॉल करना
\n\nकुछ शुरुआती बेस क्लास कंस्ट्रक्टर को सामान्य मेथड की तरह कर्ली ब्रैकेट के अंदर कॉल करने का प्रयास करते हैं। यह काम नहीं करेगा — कंस्ट्रक्टर को केवल इनिशियलाइज़ेशन लिस्ट में ही कॉल किया जा सकता है।
\n\nclass Derived : public Base {\npublic:\n Derived() {\n // त्रुटि: इस तरह कंस्ट्रक्टर कॉल नहीं होता\n Base(10); // बस एक अस्थायी ऑब्जेक्ट बनाकर उसे हटा देगा\n }\n};\n\nगलती #4: कॉपी कंस्ट्रक्टर में भ्रम
\n\nडिराइव्ड क्लास में कॉपी कंस्ट्रक्टर को लागू करते समय, बेस क्लास के कॉपी कंस्ट्रक्टर को स्पष्ट रूप से कॉल करना आवश्यक है। अन्यथा, डिफ़ॉल्ट कंस्ट्रक्टर कॉल होगा, और बेस क्लास का डेटा कॉपी नहीं होगा।
\n\nclass Derived : public Base {\npublic:\n // त्रुटि: Base गलत तरीके से कॉपी होगा\n Derived(const Derived& other) { /* ... */ }\n\n // सही:\n Derived(const Derived&