2016-04-27 7 views
7

सी ++ 11 जोड़ा गया अंतिम।क्या सी ++ अंतिम सभी पहलुओं में अंतिम रूप से अंतिम है?

अंत में!

मैं समझता हूँ final दो बातें करता है:

  • एक वर्ग गैर दाय बनाता है।
  • गैर-ओवर्रिडेबल (व्युत्पन्न कक्षा में) कक्षा में (वर्चुअल) फ़ंक्शन बनाता है।

ये दोनों एक दूसरे से स्वतंत्र प्रतीत होते हैं। लेकिन उदाहरण के लिए ले निम्नलिखित:

class Foo 
{ 
    public: 
    virtual void bar() 
    { 
     //do something unimportant. 
    } 
}; 
class Baz final : public Foo 
{ 
    public: 
    void bar() /*final*/ override 
    { 
     //do something more important than Foo's bar. 
    } 
}; 

ऊपर से, मेरा मानना ​​है कि Baz जा रहा है final, मैं नहीं कि अपनी virtual सदस्य समारोह bar भी final है निर्दिष्ट करने की आवश्यकता चाहिए। चूंकि Baz विरासत में नहीं मिला है, bar ओवरराइड करने का सवाल दायरे से बाहर हो गया है। हालांकि मेरे कंपाइलर वीसी ++ 2015, इस बारे में बहुत शांत है। मैंने इस समय किसी अन्य पर इसका परीक्षण नहीं किया है।

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

तो, मेरे सवाल यह है: परोक्ष इसकेvirtualकार्यों मतलबfinalरूप में अच्छी तरह होने के लिए एकfinal classकरता है? इसे होना चाहिए? कृपया स्पष्ट करें।


कारण मैं पूछ रहा हूँ इस वजह से final कार्यों de-वर्चुअलाइजेशन है, जो एक महान अनुकूलन है के लिए योग्य हो जाते हैं। किसी भी मदद की सराहना की है।

+2

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

+0

@ सेर्गेया हां। यही कारण है कि मैंने योग्यता लिखी। –

+2

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

उत्तर

8

कारण मैं यह पूछ रहा हूं क्योंकि अंतिम कार्य डी-वर्चुअलाइजेशन के लिए योग्य हो जाते हैं, जो एक महान अनुकूलन है।

क्या वे? "डी-वर्चुअलाइजेशन" सी ++ मानक का हिस्सा नहीं है। या कम से कम, वास्तव में नहीं।

डी-वर्चुअलाइजेशन केवल "जैसे" नियम का परिणाम है, जो कहता है कि कार्यान्वयन तब तक ऐसा कर सकता है जब तक कि कार्यान्वयन "जैसे" होता है, यह मानक कहता है।

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

इस तरह, मानक परिभाषित नहीं करता है जब डी-वर्चुअलाइजेशन की अनुमति है/वर्जित है। एक कंपाइलर, जो एक वर्चुअल टाइप में पॉइंटर लेता है, को रेखांकित करने पर, यह पता लगा सकता है कि पॉइंटर पारित होने वाले फ़ंक्शन में घोषित एक स्टैक वैरिएबल लोक को इंगित कर रहा है जिसमें इसे रेखांकित किया जा रहा है। या यह कि संकलक किसी विशेष पॉलिमॉर्फिक पॉइंटर/संदर्भ के लिए मूल बिंदु पर किसी विशेष इनलाइन/कॉल ग्राफ़ का पता लगा सकता है। उन मामलों में, संकलक उस प्रकार में कॉल को वर्चुअल कर सकता है। लेकिन केवल अगर ऐसा करने के लिए पर्याप्त स्मार्ट है।

क्या एक कंपाइलर सभी वर्चुअल फ़ंक्शन कॉल को final कक्षा में विभाजित करेगा, भले ही उन विधियों को final घोषित किया गया हो? यह शायद। यह नहीं हो सकता है यह पॉलिमॉर्फिक प्रकार पर final घोषित विधियों को किसी भी कॉल को भी छेड़छाड़ नहीं कर सकता है। यह एक वैध (यदि विशेष रूप से उज्ज्वल नहीं है) कार्यान्वयन है।

जो प्रश्न आप पूछ रहे हैं वह कार्यान्वयन विशिष्ट है। यह कंपाइलर से कंपाइलर में भिन्न हो सकता है।

हालांकि, एक वर्ग को final घोषित किया जा रहा है, जैसा कि आपने बताया है, संकलक के लिए final कक्षा प्रकार के पॉइंटर्स/संदर्भों के सभी कॉलों को व्यर्थ करने के लिए पर्याप्त जानकारी होनी चाहिए। यदि एक कंपाइलर ऐसा नहीं करता है, तो यह एक गुणवत्ता-कार्यान्वयन मुद्दा है, मानकों को एक नहीं।

+0

नहीं। संपूर्ण वर्चुअलाइजेशन तंत्र (वर्चुअल टेबल और पॉइंटर्स के साथ किया गया) मानक का हिस्सा नहीं है। मैं उम्मीद कर रहा था कि कार्यान्वयनकर्ता लागू किए गए कार्यान्वयन विवरणों के बारे में विवरण पोस्ट करेंगे। वैसे भी, स्पष्ट उत्तर के लिए +1। –

4

यहाँ [class.virtual/4] से मसौदा सी ++ मानक के शब्दों में:

कुछ वर्ग B में एक आभासी समारोह fvirt-विनिर्देशकfinal साथ और एक वर्ग DB एक समारोह से व्युत्पन्न में चिह्नित है, तो D::fB::f ओवरराइड करता है, कार्यक्रम खराब बना हुआ है।

और यहाँ [class/3]:

एक वर्ग वर्ग virt-विनिर्देशकfinal के साथ चिह्नित है और यह के रूप में प्रकट होता है एक आधार प्रकार-विनिर्देशक एक आधार खंड में (खंड [class.derived]), कार्यक्रम खराब गठित है।

तो, प्रश्न के उत्तर में;

एक finalclass परोक्ष संकेत अपने virtual कार्यों के रूप में अच्छी तरह से final होने के लिए है? इसे होना चाहिए? कृपया स्पष्ट करें।

तो, कम से कम औपचारिक रूप से नहीं। किसी भी नियम का उल्लंघन करने का कोई भी प्रयास दोनों मामलों में एक ही परिणाम होगा; कार्यक्रम खराब गठित है और संकलित नहीं होगा। एक final class का मतलब है कि वर्ग से नहीं लिया जा सकता है, इसलिए इसके परिणामस्वरूप, इसकी virtual विधियों को ओवरराइड नहीं किया जा सकता है।

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


क्वेरी के लिए आपकी प्रेरणा और वर्चुअल कॉल के डी-वर्चुअलाइजेशन को स्पर्श करने के लिए। वर्ग और न ही विधि (हालांकि वे सहायता प्रदान करते हैं) के final द्वारा तुरंत प्रभावित नहीं होते हैं, वर्चुअल फ़ंक्शंस और क्लास पदानुक्रम के सामान्य नियम लागू होते हैं।

यदि संकलक निर्धारित कर सकता है कि रनटाइम पर एक विशेष विधि हमेशा कॉल की जाएगी (उदा। स्वचालित ऑब्जेक्ट के साथ, यानी "स्टैक पर"), यह an optimisation anyway लागू कर सकता है, भले ही विधि अंतिम है या नहीं। ये अनुकूलन As-if नियम के अंतर्गत आते हैं, जो संकलक को apply any transformation तक अनुमति देता है जब तक कि अवलोकन योग्य व्यवहार जैसा होता है-मूल कोड निष्पादित किया गया था।

+0

उह? यह _ill-गठन_ कैसे है? 'अंतिम श्रेणी' को ** अपने ** ** वर्चुअल विरासत सदस्य समारोह को 'अंतिम' के रूप में इंगित करना है। ऊपर दिए गए उदाहरण दोनों परीक्षण मामलों में संकलित होते हैं: जब 'अंतिम' विनिर्देश वर्चुअल फ़ंक्शन से जुड़ा होता है और जब नहीं (बिना किसी त्रुटि/चेतावनी/सूचना संदेश के)। कृपया समझाएँ। –

+0

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

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