@SebastianRedl ने पहले ही सरल, सीधे उत्तर दिए, लेकिन कुछ अतिरिक्त स्पष्टीकरण उपयोगी हो सकते हैं।
TL; DR = कंस्ट्रक्टरों को सरल रखने के लिए एक शैली नियम है, इसके कारण हैं, लेकिन वे कारण ज्यादातर कोडिंग की एक ऐतिहासिक (या बस खराब) शैली से संबंधित हैं। कंस्ट्रक्टर्स में अपवादों की हैंडलिंग अच्छी तरह से परिभाषित है, और विध्वंसक अभी भी पूरी तरह से निर्मित स्थानीय चर और सदस्यों के लिए कॉल किए जाएंगे, जिसका अर्थ है कि मुहावरेदार सी ++ कोड में कोई समस्या नहीं होनी चाहिए। शैली का नियम वैसे भी बना रहता है, लेकिन आम तौर पर यह कोई समस्या नहीं है - सभी आरंभीकरण को कंस्ट्रक्टर में नहीं होना चाहिए, और विशेष रूप से जरूरी नहीं कि कंस्ट्रक्टर।
यह एक सामान्य शैली का नियम है कि कंस्ट्रक्टरों को परिभाषित न्यूनतम वैध राज्य स्थापित करने के लिए पूर्ण न्यूनतम करना चाहिए। यदि आपका इनिशियलाइज़ेशन अधिक जटिल है, तो इसे कंस्ट्रक्टर के बाहर संभाला जाना चाहिए। यदि कोई सस्ता-से-प्रारंभिक मूल्य नहीं है जिसे आपका निर्माता सेट कर सकता है, तो आपको एक जोड़ने के लिए अपनी कक्षा द्वारा लागू किए गए आक्रमणकारियों को कमजोर करना चाहिए। उदाहरण के लिए, यदि आपके वर्ग के प्रबंधन के लिए भंडारण आवंटित करना बहुत महंगा है, तो एक नहीं-आवंटित-अभी तक अशक्त अवस्था को जोड़ें, क्योंकि निश्चित रूप से विशेष मामले वाले राज्यों जैसे नल कभी किसी को कोई समस्या नहीं हुई। अहम।
हालांकि आम, निश्चित रूप से इस चरम रूप में यह निरपेक्ष से बहुत दूर है। विशेष रूप से, जैसा कि मेरी व्यंग्य इंगित करता है, मैं उस शिविर में हूं जो कहता है कि कमजोर पड़ने वाले आक्रमणकारियों को लगभग हमेशा बहुत अधिक कीमत मिलती है। हालांकि, शैली के नियम के पीछे कारण हैं, और कम से कम निर्माणकर्ता और मजबूत आक्रमणकारी दोनों के तरीके हैं ।
कारण स्वत: विनाशकारी सफाई से संबंधित हैं, विशेष रूप से अपवादों के चेहरे में। मूल रूप से, एक अच्छी तरह से परिभाषित बिंदु होना चाहिए जब कंपाइलर विध्वंसक कॉलिंग के लिए जिम्मेदार हो जाता है। जब आप अभी भी एक कंस्ट्रक्टर कॉल में हैं, तो ऑब्जेक्ट आवश्यक रूप से पूरी तरह से निर्मित नहीं है, इसलिए यह उस ऑब्जेक्ट के लिए डिस्ट्रक्टर को कॉल करने के लिए मान्य नहीं है। इसलिए, ऑब्जेक्ट को नष्ट करने की जिम्मेदारी केवल कंपाइलर को हस्तांतरित होती है जब कंस्ट्रक्टर सफलतापूर्वक पूरा होता है। इसे RAII (रिसोर्स एलोकेशन इनिशियलाइज़ेशन) के रूप में जाना जाता है जो वास्तव में सबसे अच्छा नाम नहीं है।
यदि कंस्ट्रक्टर के अंदर एक अपवाद फेंक दिया जाता है, तो कुछ भी भाग का निर्माण करने की आवश्यकता होती है, जिसे आम तौर पर साफ किया जाता है try .. catch
।
हालांकि, ऑब्जेक्ट के घटक जो पहले से सफलतापूर्वक निर्माण कर चुके हैं, वे पहले से ही संकलक जिम्मेदारी हैं। इसका मतलब है कि व्यवहार में, यह वास्तव में एक बड़ी बात नहीं है। जैसे
classname (args) : base1 (args), member2 (args), member3 (args)
{
}
इस कंस्ट्रक्टर का शरीर खाली है। इतने लंबे समय के लिए निर्माणकर्ताओं के रूप में base1
, member2
और member3
अपवाद सुरक्षित हैं, चिंता की कोई बात नहीं है। उदाहरण के लिए, यदि कंस्ट्रक्टर member2
थ्रो का है, तो वह कंस्ट्रक्टर खुद को साफ करने के लिए जिम्मेदार है। आधार base1
पहले से ही पूरी तरह से निर्माण किया गया था, इसलिए इसका विध्वंसक स्वचालित रूप से कहा जाएगा। member3
आंशिक रूप से निर्माण भी नहीं किया गया था, इसलिए सफाई की आवश्यकता नहीं है।
यहां तक कि जब एक निकाय होता है, तो अपवाद को फेंकने से पहले पूरी तरह से बनाए गए स्थानीय चर स्वचालित रूप से किसी अन्य फ़ंक्शन की तरह नष्ट हो जाएंगे। कन्स्ट्रक्टर बॉडी जो कच्चे पॉइंटर्स को हथियाते हैं, या "स्वयं" किसी प्रकार की अंतर्निहित स्थिति (अन्यत्र संग्रहीत) - आम तौर पर एक शुरुआत / प्राप्त फ़ंक्शन कॉल का अंत / रिलीज़ कॉल से मिलान होना चाहिए - अपवाद सुरक्षा समस्याओं का कारण बन सकता है, लेकिन वास्तविक स्थिति एक वर्ग के माध्यम से एक संसाधन को ठीक से प्रबंधित करने में विफल हो रहा है। उदाहरण के लिए यदि आप unique_ptr
निर्माण में कच्चे पॉइंटर्स को प्रतिस्थापित करते हैं, unique_ptr
तो आवश्यकता के लिए विध्वंसक को स्वचालित रूप से कहा जाएगा।
अभी भी अन्य कारणों से लोग न्यूनतम निर्माणकर्ताओं को प्राथमिकता देते हैं। एक बस इसलिए है क्योंकि शैली नियम मौजूद है, कई लोग मानते हैं कि निर्माता कॉल सस्ते हैं। इसका एक तरीका यह भी है कि अभी भी मजबूत आक्रमणकारी हैं, एक अलग कारखाना / बिल्डर वर्ग है जिसके पास कमज़ोर आक्रमणकारी हैं, और जो सामान्य सदस्य-फ़ंक्शन कॉल का उपयोग करके आवश्यक प्रारंभिक मूल्य सेट करता है। एक बार जब आपको प्रारंभिक अवस्था की आवश्यकता होती है, तो उस वस्तु को मजबूत आक्रमणकारियों के साथ वर्ग के लिए एक तर्क के रूप में पारित कर दें। वह कमजोर-इनवेरिएंट ऑब्जेक्ट के "हिम्मत को चुरा सकता है" - शब्दार्थ को स्थानांतरित करें - जो एक सस्ता (और आमतौर पर noexcept
) ऑपरेशन है।
और निश्चित रूप से आप इसे एक make_whatever ()
फ़ंक्शन में लपेट सकते हैं , इसलिए उस फ़ंक्शन के कॉल करने वालों को कमजोर-इनवेरिएंट क्लास उदाहरण देखने की आवश्यकता नहीं है।