2011-05-19 17 views
19

मैं समझता हूं कि वर्चुअल विधियां एक व्युत्पन्न कक्षा को बेस क्लास से प्राप्त विधियों को ओवरराइड करने की अनुमति देती हैं। आभासी तरीकों का उपयोग करने के लिए यह उचित/अनुचित कब है? यह हमेशा ज्ञात नहीं होता है कि कक्षा को उप वर्गीकृत किया जाएगा या नहीं। सबकुछ वर्चुअल बनाया जाना चाहिए, बस "मामले में?" या वह महत्वपूर्ण उपरि का कारण बन जाएगा?आभासी तरीकों का उपयोग करना उचित कब है?

उत्तर

6

जब आप कक्षा को डिज़ाइन करते हैं तो आपको एक इंटरफ़ेस का प्रतिनिधित्व करने के लिए एक अच्छा विचार होना चाहिए (इस मामले में आप उचित ओवरराइड करने योग्य विधियों और विनाशक वर्चुअल को चिह्नित करते हैं) या इसका उपयोग संभवतः रचना या अन्य वस्तुओं के साथ बना है।

दूसरे शब्दों में कक्षा के लिए आपका इरादा आपकी मार्गदर्शिका होना चाहिए। वर्चुअल सब कुछ बनाना अक्सर ओवरकिल होता है और कभी-कभी भ्रामक होता है कि रनटाइम बहुरूपता का समर्थन करने के लिए कौन सी विधियों का इरादा है।

-1

Design Patterns पर एक नज़र डालें। यदि आपका कोड/डिज़ाइन इनमें से एक है या समान वर्चुअल फ़ंक्शन का उपयोग करता है। अन्यथा, this

+2

-1: गोफ डिजाइन पैटर्न को लागू करने और वर्चुअल फ़ंक्शंस की आवश्यकता को लागू करने के बीच कोई कारणता संबंध नहीं है। –

3

यदि आपका कोड किसी विशेष डिज़ाइन पैटर्न का पालन कर रहा है, तो आपकी पसंद को डीपी के अपने सिद्धांतों को प्रतिबिंबित करना चाहिए। उदाहरण के लिए, यदि आप Decorator pattern कोडिंग कर रहे हैं, तो वर्चुअल होना चाहिए जो घटक घटक इंटरफ़ेस से संबंधित हैं।

अन्यथा, मैं एक विकासवादी दृष्टिकोण का पालन करना चाहता हूं, मेरे पास आभासी विधियां नहीं हैं जब तक कि मुझे लगता है कि एक पदानुक्रम आपके कोड से उभरने की कोशिश कर रहा है।

0

मेरे बिंदु आप बच्चे को कक्षा कहने पर बात और उनके तरीकों का उपयोग करें, तो आप आभासी तरीकों का उपयोग करना चाहिए करने के लिए माता पिता के वर्ग सूचक उपयोग करना चाहते हैं है।

+0

सच होने पर, मुझे नहीं लगता कि यह वास्तव में बड़े प्रश्न का उत्तर देता है "मुझे कैसे पता चलेगा कि मुझे बहुरूपता की आवश्यकता होगी?" –

2

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

6

पहले एक थोड़ा पंडिताऊ टिप्पणी - C++ standardese हम उन्हें सदस्य काम करता है, नहीं तरीकों फोन, हालांकि दो शब्दों के बराबर हैं।

मुझे सदस्य कारण वर्चुअल बनाने के दो कारण नहीं दिखते हैं।

  • "यागनी" - "आपको इसकी आवश्यकता नहीं है"। यदि आप सुनिश्चित नहीं हैं कि एक वर्ग से लिया जाएगा, मान लें कि यह सदस्य नहीं होगा और सदस्य वर्चुअल वर्चुअल नहीं करेगा। कुछ भी नहीं कहता है "रास्ते से न निकलें" जैसे गैर-आभासी विनाशक। यह इरादे के बारे में भी है। यदि यह क्लास polymorphically वर्ग का उपयोग करने का इरादा नहीं है, तो कुछ भी वर्चुअल नहीं बनाओ। यदि आप मनमाने ढंग से सदस्यों को वर्चुअल बनाते हैं तो आप Liskov Substitution Principle के दुरुपयोग को आमंत्रित कर रहे हैं और बग के उन वर्गों को ट्रैक करने और हल करने के लिए दर्दनाक हैं।
  • प्रदर्शन/मेमोरी पदचिह्न। एक वर्ग जिसमें वर्चुअल सदस्य फ़ंक्शंस नहीं है, उसे VTable (वर्चुअल टेबल, बेस क्लास पॉइंटर के माध्यम से पॉलीमोर्फिक कॉल रीडायरेक्ट करने के लिए प्रयुक्त) की आवश्यकता नहीं होती है और इस प्रकार (संभावित रूप से) मेमोरी में कम जगह लेता है। साथ ही, एक प्रत्यक्ष सदस्य फ़ंक्शन कॉल वर्चुअल सदस्य फ़ंक्शन कॉल से (संभावित रूप से) तेज है। सदस्य वर्ग वर्चुअल वर्चुअल बनाने से पहले अपनी कक्षा को समय-समय पर निराश न करें।
3

उदाहरण के लिए जावा में सदस्य कार्य 100% वर्चुअल हैं। सी ++ में इसे कोड आकार/फ़ंक्शन कॉल टाइम पेनल्टी के रूप में माना जाता है। इसके अतिरिक्त एक गैर वर्चुअल फ़ंक्शन गारंटी देता है कि फ़ंक्शन कार्यान्वयन हमेशा समान होगा (बेस क्लास ऑब्जेक्ट/संदर्भ का उपयोग करके)। "प्रभावी सी ++" में स्कॉट मेयर्स ने अधिक जानकारी में चर्चा की।

+1

तथ्य यह है कि गैर-वर्चुअल फ़ंक्शन" वही रहता है "इसे अन्य कार्यों के लिए महत्वपूर्ण है। इसमें कॉलिंग ** वर्चुअल फ़ंक्शंस शामिल होने पर सही कार्य करना कठिन होता है। –

0

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

1

मैं जल्दी से निर्धारित करने के लिए विचार करने के लिए यदि आप, समान वर्गों कि आप एक ही कार्य करने के लिए उपयोग करने के लिए जा रहे हैं के एक समूह के साथ सौदा करने जा रहे हैं रास्ता तुम जाओ परिवर्तन होने के साथ होगा एक संभव तरीके से लगता है उन कार्यों को करने के बारे में।

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

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

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

4

यह एक मुश्किल सवाल है। लेकिन पालन करने के लिए अंगूठे के कुछ दिशानिर्देश/नियम हैं।

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

मुझे लगता है कि वे काफी सरल हैं। मैं निश्चित रूप से प्रतिबिंब के एबीआई भाग को दूर करने देता हूं, डीएलएल वितरित करते समय यह केवल उपयोगी होता है।

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