यह अक्सर डिजाइन के नजरिए से उपयोगी होता है क्योंकि यह अपरिवर्तित चीजों को चिह्नित करने में सक्षम होता है। उसी तरह से const
संकलक गार्ड प्रदान करता है और इंगित करता है कि एक राज्य को बदलना नहीं चाहिए, final
यह इंगित करने के लिए इस्तेमाल किया जा सकता है कि व्यवहार को वंशानुक्रम पदानुक्रम से आगे नहीं बदलना चाहिए।
उदाहरण
एक वीडियो गेम पर विचार करें जहां वाहन खिलाड़ी को एक स्थान से दूसरे स्थान पर ले जाते हैं। सभी वाहनों को यह सुनिश्चित करने के लिए जांचना चाहिए कि वे प्रस्थान से पहले एक वैध स्थान पर यात्रा कर रहे हैं (यह सुनिश्चित करना कि स्थान पर आधार नष्ट नहीं हुआ है, जैसे)। हम गैर-आभासी इंटरफ़ेस मुहावरे (एनवीआई) का उपयोग करना शुरू कर सकते हैं यह सुनिश्चित करने के लिए कि यह चेक वाहन की परवाह किए बिना बनाया गया है।
class Vehicle
{
public:
virtual ~Vehicle {}
bool transport(const Location& location)
{
// Mandatory check performed for all vehicle types. We could potentially
// throw or assert here instead of returning true/false depending on the
// exceptional level of the behavior (whether it is a truly exceptional
// control flow resulting from external input errors or whether it's
// simply a bug for the assert approach).
if (valid_location(location))
return travel_to(location);
// If the location is not valid, no vehicle type can go there.
return false;
}
private:
// Overridden by vehicle types. Note that private access here
// does not prevent derived, nonfriends from being able to override
// this function.
virtual bool travel_to(const Location& location) = 0;
};
अब हम कहते हैं कि हमारे खेल में हमारे पास उड़ने वाले वाहन हैं, और कुछ ऐसा है जो सभी उड़ने वाले वाहनों की आवश्यकता है और आम तौर पर यह है कि उन्हें टेक-ऑफ से पहले हैंगर के अंदर एक सुरक्षा निरीक्षण जांच से गुजरना चाहिए।
यहां हम यह final
गारंटी देने के लिए उपयोग कर सकते हैं कि सभी उड़ने वाले वाहन इस तरह के निरीक्षण से गुजरेंगे और उड़ान वाहनों की इस डिजाइन आवश्यकता को भी बताएंगे।
class FlyingVehicle: public Vehicle
{
private:
bool travel_to(const Location& location) final
{
// Mandatory check performed for all flying vehicle types.
if (safety_inspection())
return fly_to(location);
// If the safety inspection fails for a flying vehicle,
// it will not be allowed to fly to the location.
return false;
}
// Overridden by flying vehicle types.
virtual void safety_inspection() const = 0;
virtual void fly_to(const Location& location) = 0;
};
final
इस तरह से उपयोग करके , हम खुद को आभासी रूप देने के लिए वंशानुक्रम पदानुक्रम (यहां तक कि बाद में, नाजुक आधार वर्ग की समस्या का मुकाबला करते हुए) के समान व्यवहार प्रदान करने के लिए गैर-आभासी इंटरफ़ेस मुहावरे के लचीलेपन का विस्तार करने के लिए प्रभावी ढंग से कर रहे हैं। इसके अलावा, हम केंद्रीय परिवर्तन करने के लिए अपने आप को विग्लिंग रूम खरीदते हैं जो सभी उड़ान वाहनों के प्रकारों को प्रभावित करता है, जो कि प्रत्येक और हर उड़ने वाले वाहन के कार्यान्वयन को संशोधित किए बिना होता है।
यह उपयोग करने का एक ऐसा उदाहरण है final
। ऐसे कई प्रसंग हैं जिनका आप सामना करेंगे, जहां किसी आभासी सदस्य के कार्य के लिए इसका कोई अर्थ नहीं है कि इसे और आगे ले जाया जाए - ऐसा करने से भंगुर डिजाइन और आपके डिजाइन आवश्यकताओं का उल्लंघन हो सकता है।
यही वह जगह final
है जहाँ एक डिज़ाइन / वास्तु के दृष्टिकोण से उपयोगी है।
यह ऑप्टिमाइज़र के दृष्टिकोण से भी उपयोगी है क्योंकि यह ऑप्टिमाइज़र को यह डिज़ाइन जानकारी प्रदान करता है जो इसे वर्चुअल फ़ंक्शन कॉल (डायनेमिक डिस्पैच ओवरहेड को समाप्त करने और अक्सर अधिक महत्वपूर्ण रूप से, कॉलर और कैली के बीच एक अनुकूलन अवरोध को समाप्त करने) की अनुमति देता है।
सवाल
टिप्पणियों से:
अंतिम और आभासी कभी एक ही समय में क्यों उपयोग किए जाएंगे?
यह दोनों के रूप में एक समारोह घोषित करने के लिए एक पदानुक्रम की जड़ में एक आधार वर्ग के लिए कोई मतलब नहीं है virtual
और final
। यह मेरे लिए काफी मूर्खतापूर्ण लगता है, क्योंकि यह संकलक और मानव पाठक दोनों को अनावश्यक हुप्स के माध्यम से कूदना पड़ता है, जो virtual
इस तरह के मामले में सीधे तौर पर बचने से बचा जा सकता है । हालाँकि, उपवर्गों को आभासी सदस्य कार्य विरासत में मिलते हैं:
struct Foo
{
virtual ~Foo() {}
virtual void f() = 0;
};
struct Bar: Foo
{
/*implicitly virtual*/ void f() final {...}
};
इस स्थिति में, Bar::f
वर्चुअल कीवर्ड का स्पष्ट रूप से उपयोग किया जाना है या नहीं , Bar::f
यह एक वर्चुअल फंक्शन है। virtual
कीवर्ड तो इस मामले में वैकल्पिक हो जाता है। तो यह समझ के लिए कर सकता है Bar::f
के रूप में निर्दिष्ट किया जा करने के लिए final
है, भले ही यह एक आभासी समारोह है ( final
कर सकते हैं केवल आभासी कार्यों के लिए इस्तेमाल किया जा)।
और कुछ लोग पसंद कर सकते हैं, स्टाइलिस्टली, स्पष्ट रूप से इंगित करने के लिए कि Bar::f
आभासी है, जैसे:
struct Bar: Foo
{
virtual void f() final {...}
};
मेरे लिए यह अनावश्यक दोनों का उपयोग करने की तरह है virtual
और final
इस संदर्भ (वैसे ही में एक ही कार्य के लिए विनिर्देशक virtual
और override
), लेकिन यह इस मामले में शैली की बात है। कुछ लोगों को लग सकता है कि virtual
यहां कुछ मूल्यवान संचार होता है, जैसे extern
बाहरी लिंकेज के साथ फ़ंक्शन घोषणाओं के लिए उपयोग करना (भले ही यह अन्य लिंकेज क्वालीफायर का अभाव हो)।