2010-06-20 9 views
12

के लिए लागू नहीं किया गया है डिस्ट्रक्टर्स डिफ़ॉल्ट रूप से वर्चुअल नहीं हैं, जब इसकी आवश्यकता नहीं होती है, तो ठीक नहीं होता है।क्यों नहीं (सी ++) वर्चुअल विनाशकों को बेस क्लास

लेकिन बेस क्लास व्युत्पन्न क्लास परिदृश्य के मामले में, क्या वर्चुअल विनाशक नहीं होने के लिए कोई उपयोग केस है? अगर संकलक शिकायत करने के लिए संभव नहीं है (क्या यह समझ में आता है) यदि कोई वर्ग बेस क्लास से प्राप्त होता है जिसमें सार्वजनिक गैर आभासी विनाशक (या कोई विनाशक) परिभाषित नहीं होता है। और इसके बारे में चेतावनी न दें।

+0

सटर ने उस पर [Virtuality] (http://www.gotw.ca/publications/mill18.htm) लिखा था। –

+0

जो एक अद्भुत पढ़ा गया था! धन्यवाद –

उत्तर

12

आपके विचार के साथ समस्या यह है कि यह कल्पना की जा सकती है कि कोई ऑप्टिमाइज़ेशन के रूप में गैर-वर्चुअल बेस क्लास विनाशक का उपयोग कर रहा है (यदि आप बेस-क्लास पॉइंटर के माध्यम से कभी भी नष्ट नहीं होने जा रहे हैं, तो गायब वर्चुअल नहीं होगा आपको चोट पहुंचाती है, और फिर भी vtable प्रविष्टि से बचाती है)।

चूंकि इसका उपयोग किया जा सकता है, इसकी अनुमति है। मुझे लगता है कि एक वैकल्पिक कंपाइलर चेतावनी एक अच्छा विचार हो सकता है, लेकिन भाषा की कल्पना में कुछ नहीं।

+1

यह मूल रूप से एकमात्र कारण है जिसे आप बेस क्लास में आभासी विनाशक नहीं चाहते हैं। गैर-आभासी विनाशक के जोखिम और जिम्मेदारी को लेकर एम्बेडेड स्थितियों में स्मृति लागत के लायक है। –

+4

@ माइकल कोहेन: फिर आपको विनाशक 'संरक्षित' बनाना चाहिए ताकि कोई आधार वर्ग सूचक का उपयोग करके अनजाने में नष्ट नहीं हो सके। –

+8

उदाहरण के लिए boost :: noncopyable ले लो। इसका अर्थ विरासत में होना है, लेकिन आप कभी भी उस बेस क्लास में डालने और हटाने के लिए कभी नहीं जा रहे हैं, इसलिए इसे वर्चुअल डॉटोर की आवश्यकता नहीं है। और एक होने के कारण vtables को शामिल करने के लिए बहुत सारे वर्गों को मजबूर किया जाएगा जो अन्यथा – jalf

8

क्योंकि यह गैर-वर्चुअल विनाशक होने के लिए पूरी तरह मान्य है। यदि उप वर्ग केवल आवंटित स्टैक होने के लिए डिज़ाइन किए गए हैं, उदाहरण के लिए, वर्चुअल विनाशक की कोई आवश्यकता नहीं है। क्लाइंट को सभी वीटीबीएल मशीनरी की आवश्यकता क्यों होती है जब कक्षा को केवल सजावटी माना जाता है?

यह एक वर्चुअल विनाशक होने के लिए भी कम समझ में आता है जब कक्षा को निजी रूप से विरासत में प्राप्त किया जाता है (कार्यान्वित-इन-टर्म)।

यह सब कहा गया है, एक विनाशक आमतौर पर सार्वजनिक और आभासी या संरक्षित होना चाहिए, जब तक कि कोई वर्ग आधार वर्ग न हो।

+1

"केवल आवंटित स्टैक होने के लिए डिज़ाइन किए गए हैं"। यह केवल समस्याग्रस्त है जब आप 'बेस' पॉइंटर से पॉलिमॉर्फिक ऑब्जेक्ट पर 'डिलीट' कहते हैं। यानी यह है कि व्युत्पन्न वर्ग को ढेर पर आवंटित करना ठीक है, भले ही आधार का विनाशक गैर-वर्चुअल है, तब तक जब तक आप ऑब्जेक्ट को पॉइंटर से व्युत्पन्न कक्षा में हटा दें, लेकिन आधार नहीं। – AraK

+1

@AraK: फिर आप विनाशक 'संरक्षित' बनाते हैं ताकि वे ऐसा नहीं कर सकें। –

5

वर्चुअल विनाशक केवल तभी आवश्यक है जब आप delete के माध्यम से ऑब्जेक्ट का पॉलीमोर्फिक विनाश करते हैं। बदले में, तुरंत गतिशील रूप से आवंटित (new -ed) ऑब्जेक्ट्स का तात्पर्य है।

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

यदि आप वस्तुओं को गतिशील रूप से आवंटित करते हैं, लेकिन उन्हें कभी भी polymorphically नष्ट नहीं करते हैं, तो आपको आभासी विनाशक की आवश्यकता नहीं है। यह उपयोग-मामलों का एक और सेट जोड़ता है जब बेस क्लास में आभासी विनाशक आवश्यक नहीं है।

2

आपके द्वारा प्रस्तावित प्रस्तावों के साथ अलग-अलग मुद्दे हैं, जिनमें से पहला पहले से ही अन्य उत्तरों में निपटाया गया है: यदि आप किसी आधार पर सूचक के माध्यम से हटाना चाहते हैं तो आपको केवल आभासी विनाशकों की आवश्यकता होती है (एक सामान्य सिफारिश या तो जनता को प्रदान करना है वर्चुअल विनाशक या संरक्षित गैर-वर्चुअल विनाशक जो बेस क्लास के माध्यम से हटाने को रोक देगा)।

उसमें एक और मुद्दा है जब एक कंपाइलर कक्षा परिभाषा को देखता है, यह संभवतः यह नहीं जान सकता कि यह व्युत्पन्न किया जा रहा है या नहीं। विचार करें कि क्या आप एक अनुवाद इकाई में बेस क्लास लागू करते हैं। बाद में आप कक्षा से निकलते हैं। यदि वह व्युत्पन्न कन्स्ट्रक्टर वर्चुअल बनाने का संकेत देगा, तो बेस क्लास अनुवाद को फिर से सम्मिलित करना होगा, या फिर आपके प्रोग्राम में ओडीआर (वन डेफिनिशन नियम) टूटा जाएगा।

यदि आप मिश्रण में अन्य अनुवाद इकाइयां जोड़ते हैं, तो चीजें और भी बदतर हो जाती हैं।जब भी आप एक अनुवाद इकाई से हेडर फ़ाइल शामिल करते हैं तो आपको मैन्युअल रूप से को कम से कम एक शीर्षलेख शामिल करना होगा जहां उस वर्ग से व्युत्पन्न वस्तु परिभाषित की जाती है (बढ़ते युग्मन), या फिर, संकलक एक अलग परिभाषा उत्पन्न करेगा उस अनुवाद इकाई में उस एकल वर्ग के लिए (अनुवाद इकाई की तुलना में जहां व्युत्पन्न वर्ग परिभाषित किया गया है) ओडीआर को फिर से तोड़ना।

समस्या यह है कि संकलक केवल आपके प्रोजेक्ट का आंशिक दृश्य है, और वास्तव में यह नहीं देख सकता कि आपको क्या चाहिए/जो चाहिए उसे देखना चाहिए।