(निष्कर्ष देखने के लिए अगर आप जल्दी में हैं अंत पर जाएं।)
दोनों override
और final
एक आभासी समारोह में केवल घोषणा में दिखाई दे सकता है। और दोनों महत्वपूर्ण शब्दों का उपयोग उसी कार्य घोषणा में किया जा सकता है, लेकिन क्या यह दोनों का उपयोग करने के लिए उपयोगी है, दोनों स्थितियों पर निर्भर करता है।
एक उदाहरण के रूप में निम्नलिखित कोड डालें:
#include <iostream>
using std::cout; using std::endl;
struct B {
virtual void f1() { cout << "B::f1() "; }
virtual void f2() { cout << "B::f2() "; }
virtual void f3() { cout << "B::f3() "; }
virtual void f6() final { cout << "B::f6() "; }
void f7() { cout << "B::f7() "; }
void f8() { cout << "B::f8() "; }
void f9() { cout << "B::f9() "; }
};
struct D : B {
void f1() override { cout << "D::f1() "; }
void f2() final { cout << "D::f2() "; }
void f3() override final { cout << "D::f3() "; } // need not have override
// should have override, otherwise add new virtual function
virtual void f4() final { cout << "D::f4() "; }
//virtual void f5() override final; // Error, no virtual function in base class
//void f6(); // Error, override a final virtual function
void f7() { cout << "D::f7() "; }
virtual void f8() { cout << "D::f8() "; }
//void f9() override; // Error, override a nonvirtual function
};
int main() {
B b; D d;
B *bp = &b, *bd = &d; D *dp = &d;
bp->f1(); bp->f2(); bp->f3(); bp->f6(); bp->f7(); bp->f8(); bp->f9(); cout << endl;
bd->f1(); bd->f2(); bd->f3(); bd->f6(); bd->f7(); bd->f8(); bd->f9(); cout << endl;
dp->f1(); dp->f2(); dp->f3(); dp->f6(); dp->f7(); dp->f8(); dp->f9(); cout << endl;
return 0;
}
उत्पादन
B::f1() B::f2() B::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() D::f7() D::f8() B::f9()
f1()
और f6()
की तुलना है। हम जानते हैं कि override
और final
सैद्धांतिक रूप से अप्रिय है।
override
का अर्थ है कि फ़ंक्शन अपनी बेस क्लास में वर्चुअल फ़ंक्शन ओवरराइड कर रहा है। f1()
और f3()
देखें।
final
का अर्थ है कि फ़ंक्शन को व्युत्पन्न कक्षा से ओवरराइड नहीं किया जा सकता है। (लेकिन फ़ंक्शन को बेस क्लास वर्चुअल फ़ंक्शन को ओवरराइड करने की आवश्यकता नहीं है।) f6()
और f4()
देखें।
f2()
और f3()
की तुलना करें। हम जानते हैं कि यदि सदस्य फ़ंक्शन को virtual
के बिना घोषित किया गया है और final
के साथ, इसका मतलब है कि यह पहले से ही बेस क्लास में वर्चुअल फ़ंक्शन को ओवरराइड करता है। इस मामले में, कुंजी शब्द override
अनावश्यक है।
f4()
और f5()
की तुलना करें। हम जानते हैं कि यदि सदस्य फ़ंक्शन virtual
के साथ घोषित किया गया है और यदि यह पहले विरासत पदानुक्रम में वर्चुअल फ़ंक्शन नहीं है, तो हमें ओवरराइड संबंध निर्दिष्ट करने के लिए override
का उपयोग करना चाहिए। अन्यथा, हम गलती से व्युत्पन्न कक्षा में नए वर्चुअल फ़ंक्शन को जोड़ सकते हैं।
f1()
और f7()
की तुलना करें। हम जानते हैं कि किसी भी सदस्य फ़ंक्शन, न केवल वर्चुअल वाले, को व्युत्पन्न कक्षा में ओवरराइड किया जा सकता है। virtual
निर्दिष्ट करता है पॉलिमॉर्फिज्म, जिसका अर्थ है कि चलाने के लिए कौन सा फ़ंक्शन संकलित समय के बजाए रन टाइम तक देरी हो रही है। (यह अभ्यास में से बचना चाहिए।)
f7()
और f8()
की तुलना करें। हम जानते हैं कि हम बेस क्लास फ़ंक्शन को ओवरराइड भी कर सकते हैं और इसे एक नया आभासी बना सकते हैं। (किसी भी सदस्य समारोह D
से प्राप्त आभासी हो जाएगा वर्ग के f8()
। इसका मतलब है) (यह व्यवहार में भी बचने की जानी चाहिए।)
f7()
और f9()
की तुलना करें। हम जानते हैं कि override
हमें त्रुटि प्राप्त करने में मदद कर सकता है जब हम व्युत्पन्न कक्षा में वर्चुअल फ़ंक्शन को ओवरराइड करना चाहते हैं, जबकि बेस क्लास में virtual
कुंजी शब्द जोड़ना भूल गए हैं।
निष्कर्ष में, अपने ही ध्यान में रखते हुए सबसे अच्छा अभ्यास है: आधार वर्ग में पहले आभासी समारोह की घोषणा में
- केवल उपयोग
virtual
;
- व्युत्पन्न कक्षा में वर्चुअल फ़ंक्शन ओवरराइड निर्दिष्ट करने के लिए हमेशा
override
का उपयोग करें, जब तक कि final
निर्दिष्ट न हो।
का उपयोग करें, मुझे आपका उत्तर पसंद है, लेकिन मैं इसे एक व्यावहारिक बिंदु से स्पष्ट करना चाहता हूं 'वर्चुअल शून्य एफ() अंतिम ओवरराइड' और 'शून्य एफ() फ़ाइनल' को इस अर्थ में समतुल्य समझा जाता है कि अगर वे कुछ ओवरराइड नहीं करते हैं तो दोनों विफल हो जाते हैं। 'अंतिम' केवल वर्चुअल फ़ंक्शंस के लिए मान्य है और 'f' की बाद की घोषणा केवल वर्चुअल है यदि यह किसी फ़ंक्शन को ओवरराइड करता है। बाद वाले के लिए त्रुटि संदेश हालांकि कम सटीक हो सकता है। –
* बाद की घोषणा इरादे को स्पष्ट करती है * - मुझे ऐसा नहीं लगता है। आपके विवरण ने मुझे पहली घोषणा शैली ** को प्राथमिकता दी है, उसी कारण से मैं वर्चुअल विधि को ओवरराइड करते समय 'आभासी' जोड़ने से बचूंगा: इसमें कोई मान नहीं है। लेकिन यह निश्चित रूप से 'वर्चुअल शून्य foo() फ़ाइनल लिखने से बेहतर है; ' – Wolf
@Wolf आपको नहीं लगता कि यह स्पष्ट मंशा व्यक्त करता है? क्या आप पहले घोषणापत्र द्वारा व्यक्त किए गए इरादे को स्पष्ट रूप से व्यक्त कर सकते हैं? – Columbo