2010-04-09 23 views
38

मुझे हाल ही में पता चला कि सी ++ शुद्ध आभासी कार्यों में वैकल्पिक रूप से एक शरीर हो सकता है।शरीर के साथ शुद्ध आभासी कार्यों के उपयोग के मामले?

ऐसे कार्यों के लिए वास्तविक दुनिया के उपयोग के मामले क्या हैं?

+2

http://stackoverflow.com/questions/2089083/pure-virtual-function-with-implementation – patros

+5

@patros: किसी थ्रेड में कोई भी उत्तर * वास्तविक दुनिया उपयोग केस * का वर्णन नहीं करता है। तो, नहीं, मुझे नहीं लगता कि यह एक डुप्ली है। – missingfaktor

उत्तर

31

क्लासिक एक शुद्ध आभासी नाशक है:

class abstract { 
    public: 
    virtual ~abstract() = 0; 
}; 

abstract::~abstract() {} 

आप इसे शुद्ध वहाँ बहुत बनाने के लिए और कुछ नहीं है, और आप वर्ग सार होना चाहते हैं क्योंकि बनाने, लेकिन आप फिर भी एक कार्यान्वयन प्रदान करने के लिए है, क्योंकि है व्युत्पन्न वर्गों के विनाशक आपकी स्पष्ट रूप से कॉल करते हैं। हाँ, मुझे पता है, एक सुंदर मूर्ख पाठ्यपुस्तक उदाहरण है, लेकिन जैसा कि यह एक क्लासिक है। यह The C++ Programming Language के पहले संस्करण में होना चाहिए।

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

यदि आपको कभी लगता है कि आपको इस सुविधा की आवश्यकता है, तो आप शायद अपने डिजाइन के साथ गलत ट्रैक पर हैं।

+3

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

+1

@ माइकल: मुझे इस आलोचना को पता है। (वास्तव में, मैंने अपने उत्तर में बहुत कुछ लिखा है।) समस्या यह है कि, मैं शुद्ध वर्चुअल फ़ंक्शन को लागू करने के किसी भी अच्छे कारण के बारे में नहीं सोच सकता। जैसा कि मैंने लिखा है, अगर आपको लगता है कि आपको ऐसा करने की ज़रूरत है, तो यह संभावना है कि आप गलत ट्रैक पर हैं। – sbi

+0

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

27

शरीर के साथ या उसके बिना शुद्ध वर्चुअल फ़ंक्शंस का मतलब यह है कि व्युत्पन्न प्रकारों को अपना स्वयं का कार्यान्वयन प्रदान करना चाहिए।

बेस क्लास में शुद्ध वर्चुअल फ़ंक्शन बॉडी उपयोगी हैं यदि आपके व्युत्पन्न कक्षाएं आपके बेस क्लास कार्यान्वयन को कॉल करना चाहती हैं।

8

एक उपयोग केस कन्स्ट्रक्टर या कक्षा के विनाशक से शुद्ध वर्चुअल फ़ंक्शन को कॉल कर रहा है।

+1

+1: यह वास्तव में मुख्य मामला है। कुछ केवल एकमात्र मामला कह सकते हैं। –

+0

लेकिन शुद्ध वर्चुअल कन्स्ट्रक्टर जैसी कोई चीज़ नहीं है, जो आपकी पोस्ट को इंगित करती है। –

+3

@ जॉन: मैंने इसे अलग पढ़ा। हालांकि, मुझे लगता है कि वर्चुअल फ़ंक्शंस को कॉल करना, शुद्ध या नहीं, सीटीओर्स या डिटर्स से वैसे भी एक बहुत संदिग्ध अभ्यास है। – sbi

4

शरीर के साथ वर्चुअल फ़ंक्शन का केवल अंतर और शरीर के साथ शुद्ध वर्चुअल फ़ंक्शन यह है कि दूसरे रोकथाम के अस्तित्व का अस्तित्व है। आप सी ++ में कक्षा सारणी को चिह्नित नहीं कर सकते हैं।

16

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

class foo { 
public: 
    virtual int interface(); 
}; 

int foo::interface() 
{ 
    printf("default foo::interface() called\n"); 
    return 0; 
}; 


class pure_foo { 
public: 
    virtual int interface() = 0; 
}; 

int pure_foo::interface() 
{ 
    printf("default pure_foo::interface() called\n"); 
    return 42; 
} 

//------------------------------------ 

class foobar : public foo { 
    // no need to override to get default behavior 
}; 

class foobar2 : public pure_foo { 
public: 
    // need to be explicit about the override, even to get default behavior 
    virtual int interface(); 
}; 

int foobar2::interface() 
{ 
    // foobar is lazy; it'll just use pure_foo's default 
    return pure_foo::interface(); 
} 

मैं वहाँ लाभ की एक पूरी बहुत कुछ है यकीन नहीं है - हो सकता है मामलों में जहां एक डिजाइन एक अमूर्त वर्ग के साथ बाहर शुरू कर दिया है, तो समय के साथ पाया गया कि व्युत्पन्न ठोस वर्ग का एक बहुत ही व्यवहार को लागू किया गया था , इसलिए उन्होंने शुद्ध वर्चुअल फ़ंक्शन के लिए उस व्यवहार को बेस क्लास कार्यान्वयन में स्थानांतरित करने का निर्णय लिया।

मुझे लगता है कि सामान्य वर्चुअल फ़ंक्शन के बेस क्लास कार्यान्वयन में सामान्य व्यवहार को रखना उचित हो सकता है कि व्युत्पन्न कक्षाओं को संशोधित/बढ़ाने/बढ़ाने की अपेक्षा की जा सकती है।

+0

@ रिचर्ड जॉर्ज: क्या आप समझा सकते हैं कि सही तरीके से निष्पादित नहीं किया जा रहा है? यह काम कर रहा है जैसा कि मैं उम्मीद करता हूं, लेकिन शायद आप मुझसे अलग उपयोग मामले देख रहे हैं। –

+0

@Micheal, यह ठीक काम करता है, मैं आपके अपने उपयोग के मामले में थोड़ा गड़बड़ कर रहा हूं, आपके लिए +1। –

7

सी ++ मानक समिति की पूर्व कुर्सी, did give 3 scenarios पर सर्वशक्तिमान हर्ब सटर, जहां आप शुद्ध आभासी तरीकों के लिए कार्यान्वयन प्रदान करने पर विचार कर सकते हैं।

यह कहना होगा कि व्यक्तिगत रूप से - मुझे उनमें से कोई भी विश्वास नहीं करता है, और आमतौर पर इसे सी ++ के अर्थपूर्ण मौसा माना जाता है।ऐसा लगता है कि सी ++ अमूर्त-अभिभावक vtables को अलग करने के लिए अपने रास्ते से बाहर निकलता है, केवल बाल निर्माण/विनाश के दौरान उन्हें संक्षेप में उजागर करता है, and then समुदाय विशेषज्ञ सर्वसम्मति से never to use them की अनुशंसा करते हैं।

+1

वह सटर लेख उत्कृष्ट है। मेरे लिए कुछ अस्पष्ट विचारों को मंजूरी दे दी। – DarenW

+0

मुझे सार-अभिभावक vtables के साथ संबंध नहीं दिख रहा है। – curiousguy

2

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

भ्रम इस तथ्य के लिए आता है कि कई डेवलपर्स शुद्ध वर्चुअल फ़ंक्शन को परिभाषित करने के प्राथमिक लक्ष्य/लाभ के रूप में कोई शरीर/कार्यान्वयन नहीं मानते हैं। यह सच नहीं है! शरीर की अनुपस्थिति ज्यादातर मामलों में शुद्ध वर्चुअल फ़ंक्शन होने का तार्किक परिणाम है। शुद्ध वर्चुअल फ़ंक्शन रखने का मुख्य लाभ एक अनुबंध को समाप्त करना है! एक शुद्ध वर्चुअल फ़ंक्शन को परिभाषित करके, आप हमेशा से प्राप्त किए गए प्रत्येक को फंक्शन के अपने कार्यान्वयन को प्रदान करना चाहते हैं। यह "अनुबंध पहलू" बहुत महत्वपूर्ण है, खासकर यदि आप सार्वजनिक एपीआई की तरह कुछ विकसित कर रहे हैं। फ़ंक्शन केवल वर्चुअल बनाना इतना पर्याप्त नहीं है क्योंकि डेरिवेटिव को अब अपना कार्यान्वयन प्रदान करने के लिए मजबूर नहीं किया जाता है, इसलिए आप अनुबंध पहलू को खो सकते हैं (यह सार्वजनिक एपीआई के मामले में सीमित हो सकता है)। जैसा कि आमतौर पर कहा गया है: "आभासी कार्यों को ओवरराइड किया जा सकता है, शुद्ध वर्चुअल फ़ंक्शन को ओवरराइड किया जाना चाहिए।" और ज्यादातर मामलों में, अनुबंध अमूर्त अवधारणाएं हैं, इसलिए यह किसी भी कार्यान्वयन के लिए संबंधित शुद्ध आभासी कार्यों के लिए समझ में नहीं आता है।

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

उपरोक्त उद्धृत लेखक आलेख शरीर के साथ शुद्ध वर्चुअल फ़ंक्शंस रखने के दिलचस्प उपयोग के मामलों को देता है।

+0

सटर लेख कहां है? मैं इसे अंतिम वाक्य में आपकी टिप्पणी के अलावा अन्य नहीं देखता हूं * "... ऊपर दिए गए सटर लेख ..." *। – jww

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