2010-02-04 18 views
65

यदि मेरे पास वर्चुअल विनाशक के साथ बेस क्लास है। एक व्युत्पन्न वर्ग भी एक आभासी विनाशक घोषित करने के लिए है?आभासी विनाशक विरासत में हैं?

class base { 
public: 
    virtual ~base() {} 
}; 

class derived : base { 
public: 
    virtual ~derived() {} // 1) 
    ~derived() {} // 2) 
}; 

कंक्रीट सवाल:

  1. है 1) और 2) एक ही? 2) स्वचालित रूप से वर्चुअल है क्योंकि यह आधार है या यह वर्चुअलनेस को "रोक" देता है?
  2. क्या व्युत्पन्न विनाशक को छोड़ दिया जा सकता है यदि उसके पास कुछ भी नहीं है?
  3. व्युत्पन्न विनाशक घोषित करने के लिए सबसे अच्छा अभ्यास क्या है? इसे आभासी, गैर-वर्चुअल घोषित करें या यदि संभव हो तो इसे छोड़ दें?

उत्तर

82
  1. हाँ, वे वही हैं। व्युत्पन्न वर्ग कुछ वर्चुअल घोषित नहीं करता है, यह वर्चुअल होने से नहीं रोकता है। वास्तव में, किसी भी विधि (विनाशक शामिल) को व्युत्पन्न वर्ग में वर्चुअल होने से रोकने का कोई तरीका नहीं है, यदि यह बेस क्लास में वर्चुअल था। इन = = सी ++ 11 आप व्युत्पन्न कक्षाओं में ओवरराइड होने से रोकने के लिए final का उपयोग कर सकते हैं, लेकिन यह इसे वर्चुअल होने से नहीं रोकता है।
  2. हां, व्युत्पन्न वर्ग में एक विनाशक को छोड़ा जा सकता है यदि उसके पास कुछ भी नहीं है। और इससे कोई फर्क नहीं पड़ता कि यह वर्चुअल है या नहीं।
  3. यदि संभव हो तो मैं इसे छोड़ दूंगा। और स्पष्टता के कारणों के लिए व्युत्पन्न कक्षाओं में आभासी कार्यों के लिए मैं हमेशा virtual कीवर्ड का उपयोग करता हूं। लोगों को यह पता लगाने के लिए विरासत पदानुक्रम को सभी तरह से नहीं जाना चाहिए कि एक कार्य आभासी है। इसके अतिरिक्त, यदि आपकी कक्षा आपकी प्रतिलिपि घोषित करने या रचनाकारों को स्थानांतरित करने के बिना प्रतिलिपि बनाने योग्य या चलती है, तो किसी भी प्रकार का विनाशक घोषित करता है (भले ही आप इसे default के रूप में परिभाषित करते हैं) आपको प्रतिलिपि घोषित करने और कन्स्ट्रक्टर और असाइनमेंट ऑपरेटर को स्थानांतरित करने के लिए मजबूर करेगा उन्हें चाहते हैं क्योंकि कंपाइलर अब उन्हें आपके लिए नहीं रखेगा।

आइटम 3 के लिए एक छोटे बिंदु के रूप में। यह टिप्पणियों में बताया गया है कि यदि एक विनाशक अव्यवस्थित है तो संकलक एक डिफ़ॉल्ट (जो अभी भी आभासी है) उत्पन्न करता है। और वह डिफ़ॉल्ट एक इनलाइन फ़ंक्शन है।

इनलाइन फ़ंक्शंस संभावित रूप से आपके प्रोग्राम के अन्य हिस्सों में बदलाव के लिए आपके प्रोग्राम का अधिक खुलासा करते हैं और साझा पुस्तकालयों के लिए बाइनरी संगतता बनाते हैं। इसके अलावा, बढ़ते युग्मन के परिणामस्वरूप कुछ प्रकार के परिवर्तनों के मुकाबले बहुत सारे पुनर्मूल्यांकन हो सकते हैं। उदाहरण के लिए, यदि आप तय करते हैं कि आप वास्तव में अपने आभासी विनाशक के लिए कार्यान्वयन चाहते हैं तो कोड के प्रत्येक टुकड़े को इसे फिर से सम्मिलित करने की आवश्यकता होगी। जबकि अगर आपने इसे कक्षा के शरीर में घोषित कर दिया था और फिर इसे .cpp फ़ाइल में खाली कर दिया था तो आप बिना किसी संकलन के इसे ठीक से बदल देंगे।

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

+0

आपकी आखिरी वाक्य शायद "चाहिए" के बजाय "नहीं" पढ़नी चाहिए। –

+0

@ क्रिस लुट्ज़, मैं आपसे आगे हूं। इसे अब सबमिशन में संपादित किया गया है। :-) – Omnifarious

+1

मैं 'ओमिट' भाग से असहमत हूं। इसे हेडर में घोषित करने और स्रोत में इसे खाली (खाली निकाय) परिभाषित करने के लिए बहुत अधिक लागत नहीं है। यदि आप ऐसा करते हैं, तो आप हमेशा वापस आ सकते हैं और अपने ग्राहकों को पुन: संकलित करने के लिए मजबूर किए बिना कुछ कदम (लॉगिंग?) जोड़ सकते हैं। –

1

एक वर्चुअल सदस्य फ़ंक्शन इस फ़ंक्शन वर्चुअल के किसी भी ओवरलोडिंग को निश्चित रूप से बनाएगा।

तो वर्चुअल 1) "वैकल्पिक" है, बेस क्लास विनाशक वर्चुअल होने से सभी बच्चे विनाशक वर्चुअल भी बनाता है।

1
  1. विनाशक स्वचालित रूप से वर्चुअल है, सभी विधियों के साथ। आप C++ में वर्चुअल होने से किसी विधि को रोक नहीं सकते हैं (यदि इसे पहले ही वर्चुअल घोषित किया गया है, यानी, यानी।जावा में 'अंतिम' के बराबर नहीं है)
  2. हां इसे छोड़ा जा सकता है।
  3. यदि मैं इस वर्ग को उप-वर्गीकृत करने का इरादा रखता हूं तो मैं एक आभासी विनाशक घोषित करता हूं, इससे कोई फर्क नहीं पड़ता कि यह किसी अन्य वर्ग को उपclassing है या नहीं, मैं भी वर्चुअल विधियों को घोषित करना पसंद करता हूं, भले ही इसकी आवश्यकता नहीं है। यह subclasses काम कर रहेगा, क्या आप कभी विरासत को हटाने का फैसला करना चाहिए। लेकिन मुझे लगता है कि यह सिर्फ शैली का मामला है।
+0

विनाशक स्वचालित रूप से आभासी नहीं हैं, और न ही कोई अन्य सदस्य कार्य हैं। –

+1

@Neil; बेशक नहीं, मैं उदाहरण में _the_ विनाशक का जिक्र कर रहा था (यानी जहां बेस क्लास में वर्चुअल एक है), सामान्य रूप से विनाशक नहीं। और यह सभी विधियों के लिए सच है, न केवल विनाशकों। – falstro

0

1/हाँ 2/हाँ, यह संकलक 3 द्वारा उत्पन्न हो जाएगा/यह आभासी घोषित करने या नहीं ओवरराइड आभासी सदस्यों के लिए अपने का पालन करना चाहिए के बीच विकल्प - IMHO, वहाँ अच्छा तर्क दोनों तरह से कर रहे हैं , बस एक चुनें और इसका पालन करें।

यदि संभव हो तो मैं इसे छोड़ दूंगा, लेकिन एक ऐसी चीज है जो आपको इसे घोषित करने के लिए उत्तेजित कर सकती है: यदि आप संकलित जनरेटर का उपयोग करते हैं, तो यह निश्चित रूप से इनलाइन है। ऐसे समय हैं जब आप इनलाइन सदस्यों से बचना चाहते हैं (उदाहरण के लिए गतिशील पुस्तकालय)।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^