दिलचस्प पोस्ट
यूनिट टेस्ट बनाम फंक्शनल टेस्ट एकाधिक अक्षर पायथन के साथ बदलते हैं सी ++ फिक्स्ड प्वाइंट लाइब्रेरी? HTTP प्रतिक्रिया भेजने के बाद php प्रसंस्करण जारी रखें सी कैसे कंसोल के लिए एक द्विआधारी पेड़ "आकर्षित" एक वेक्टर से तत्वों को मिटाना केस बनाम DECODE उपडोमेन के लिए डोमेन सेट कुकी mongodb कर्सर id मान्य त्रुटि नहीं है सी ++ में टेल रिकर्सन स्ट्रिंग के लिए जावा की आंतरिक प्रतिवेदन क्या है? संशोधित UTF-8? UTF-16? लक्ष्य निर्भरता के लिए एक्सकोडबिल्ड अलग प्रावधान प्रोफाइल कैसे लिनक्स थ्रेड्स और प्रक्रिया शेड्यूलिंग को संभालता है एक 16-बिट RGB565 को 24-बिट RGB888 में कैसे परिवर्तित करता है? मैं कैसे जाँच सकता हूँ कि एक सरणी php में एक विशिष्ट मान है?

अधिभार संकल्प और आभासी विधियों

निम्नलिखित कोड पर विचार करें (यह थोड़ा लंबा है, लेकिन उम्मीद है कि आप का पालन कर सकते हैं):

class A { } class B : A { } class C { public virtual void Foo(B b) { Console.WriteLine("base.Foo(B)"); } } class D: C { public override void Foo(B b) { Console.WriteLine("Foo(B)"); } public void Foo(A a) { Console.WriteLine("Foo(A)"); } } class Program { public static void Main() { B b = new B(); D d = new D (); d.Foo(b); } } 

यदि आपको लगता है कि इस कार्यक्रम का उत्पादन "फू (बी)" है तो आप उसी नाव में होंगे जैसे: पूरी तरह से गलत! वास्तव में, यह "फू (ए)" का उत्पादन करता है

अगर मैं C क्लास से वर्चुअल विधि को निकालता हूं, तो यह अपेक्षा के अनुरूप काम करता है: "फू (बी)" आउटपुट है

कंपाइलर उस संस्करण का चयन क्यों करता है जो A लेता है जब B अधिक-व्युत्पन्न वर्ग होता है?

Solutions Collecting From Web of "अधिभार संकल्प और आभासी विधियों"

उत्तर सी # विनिर्देश अनुभाग 7.3 और खंड 7.5.5.1 में है

मैंने शुरू करने के लिए विधि को चुनने के लिए इस्तेमाल किए गए चरणों को तोड़ दिया।

  • सबसे पहले, टी ( T=class D ) में घोषित एन ( N=Foo ) नामक सभी पहुंच वाले सदस्यों का सेट और आधारभूत प्रकार टी ( class C ) का निर्माण किया गया है। ओवरराइड संशोधक को शामिल करने वाले घोषणाओं को सेट से बाहर रखा गया है ( D.Foo (B)) बहिष्कृत है

     S = { C.Foo(B) ; D.Foo(A) } 
  • विधि के आवागमन के लिए उम्मीदवार के तरीकों का सेट बनाया गया है। एम के साथ संबद्ध विधियों के सेट से प्रारंभ करना, जो पिछले सदस्य लुकअप द्वारा पाए गए थे, सेट उन विधियों में कम कर दिया जाता है जो तर्क सूची AL ( AL=B ) के संबंध में लागू होते हैं। सेट में कमी सेट में प्रत्येक विधि टीएन के लिए निम्नलिखित नियमों को लागू करने के लिए होते हैं, जहां टी ( T=class D ) एक प्रकार है जिसमें विधि N ( N=Foo ) घोषित की जाती है:

    • यदि एन AL ( धारा 7.4.2.1 ) के संबंध में लागू नहीं है, तो N सेट से हटा दिया गया है।

      • C.Foo(B) ए एल के संबंध में लागू है
      • D.Foo(A) के संबंध में ए एल के संबंध में लागू है

         S = { C.Foo(B) ; D.Foo(A) } 
    • अगर एन AL (धारा 7.4.2.1) के संबंध में लागू है, तो आधारभूत प्रकार टी में घोषित सभी विधियों को सेट से हटा दिया जाता हैC.Foo(B) को सेट से हटा दिया गया है

        S = { D.Foo(A) } 

अंत में विजेता D.Foo(A)D.Foo(A)


अगर अमूर्त पद्धति को सी से निकाल दिया जाता है

अगर सार पद्धति को सी से निकाल दिया जाता है, तो प्रारंभिक सेट S = { D.Foo(B) ; D.Foo(A) } S = { D.Foo(B) ; D.Foo(A) } और उस सेट में सर्वश्रेष्ठ फ़ंक्शन सदस्य का चयन करने के लिए अधिभार संकल्प नियम का उपयोग किया जाना चाहिए।

इस मामले में विजेता D.Foo(B)D.Foo(B)

कंपाइलर उस संस्करण का चयन क्यों करता है जो ए को लेता है जब बी अधिक-व्युत्पन्न वर्ग होता है?

जैसा कि अन्य लोगों ने ध्यान दिया है, संकलक ऐसा इसलिए करता है क्योंकि भाषा विनिर्देश क्या करता है।

यह एक असंतुष्ट उत्तर हो सकता है एक प्राकृतिक अनुवर्ती "क्या डिजाइन सिद्धांतों को इस तरह से भाषा निर्दिष्ट करने के निर्णय के अधीन होंगे?"

यह एक बार पूछे जाने वाले सवाल है, दोनों StackOverflow पर और मेरे मेलबॉक्स में संक्षिप्त जवाब यह है कि "यह डिज़ाइन बग़ल बेस क्लास परिवार की बग्स को कम करता है।"

इस सुविधा के विवरण के लिए और इसे किस तरह से डिजाइन किया गया है, इस विषय पर मेरा आलेख देखें:

http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx

इस विषय पर अधिक लेख के लिए कि विभिन्न भाषाओं में भंगुर आधार वर्ग की समस्याओं का कैसे निपटारा है, इस विषय पर लेखों का मेरा संग्रह देखें:

http://blogs.msdn.com/b/ericlippert/archive/tags/brittle+base+classes/

पिछले हफ्ते से ही एक ही प्रश्न का मेरा जवाब है, जो इस तरह एक उल्लेखनीय लग रहा है।

बेस क्लास में हस्ताक्षर क्यों घोषित किए गए हैं?

और यहां तीन और अधिक प्रासंगिक या डुप्लिकेट किए गए प्रश्न हैं:

सी # ओवरलोडिंग संकल्प?

विधि अधिभार संकल्प और जॉन स्कीट के मस्तिष्क टीज़र

यह काम क्यों करता है? विधि ओवरलोडिंग + विधि ओवरराइडिंग + बहुरूपता

मुझे लगता है कि ऐसा इसलिए है क्योंकि एक गैर-आभासी पद्धति के अनुसार जिस विधि पर विधि लागू की जाती है उसका संकलन समय प्रकार उपयोग किया जाता है।

आपके पास Foo विधि है जो गैर-आभासी है और इसलिए उस विधि को कहा जाता है।

इस लिंक में बहुत अच्छी व्याख्या है http://msdn.microsoft.com/en-us/library/aa645767%28VS.71%29.aspx

इसलिए, यहां बताया गया है कि यह विनिर्देश के अनुसार काम करना चाहिए (समय संकलित करने पर, और मैंने दस्तावेजों को सही तरीके से नेविगेट किया है):

संकलक विधि नाम और तर्क सूची के आधार पर, प्रकार D और इसके आधार प्रकारों से मिलान विधि की एक सूची को पहचानता है। इसका अर्थ है कि Foo नामित कोई भी विधि, एक प्रकार का एक पैरामीटर ले रहा है, जिसमें B से एक अप्रत्यक्ष रूपान्तरण है, वैध उम्मीदवार हैं। यह निम्नलिखित सूची तैयार करेगा:

 C.Foo(B) (public virtual) D.Foo(B) (public override) D.Foo(A) (public) 

इस सूची से, ओवरराइड संशोधक को शामिल करने वाले किसी भी घोषणा को बाहर रखा गया है। इसका मतलब है कि सूची में अब निम्नलिखित विधियां हैं:

 C.Foo(B) (public virtual) D.Foo(A) (public) 

इस समय हमारे पास मिलान करने वाले उम्मीदवारों की सूची है, और संकलक अब तय है कि क्या कॉल करें। दस्तावेज़ 7.5.5.1 विधि invocations में , हम निम्नलिखित पाठ पाते हैं:

यदि एन ए ( धारा 7.4.2.1 ) के संबंध में लागू है, तो आधारभूत प्रकार टी में घोषित सभी विधियों को सेट से हटा दिया जाता है।

इसका अनिवार्य रूप से अर्थ है कि यदि D में घोषित एक लागू विधि है, तो बेस क्लास से कोई भी विधि सूची से हटा दी जाएगी। इस बिंदु पर हमारे पास विजेता है:

 D.Foo(A) (public) 

मुझे लगता है कि जब किसी अन्य वर्ग को कार्यान्वित करते हैं तो यह एक विधि के ठोस कार्यान्वयन के लिए पेड़ तक दिखता है। चूंकि इसे कोई आधार नहीं कहा जाता है क्योंकि यह बेस क्लास का उपयोग कर रहा है।

 सार्वजनिक शून्य फू (ए ए) {
     कंसोल.प्रकाशलाइन ("फू (ए)" + a.GetType ()। नाम);
     कंसोल.प्रकाशलाइन ("फू (ए)" + a.GetType ()। बेसटाइप);
 }

अनुमान लगाता है कि मैं .Net पर कोई समर्थक नहीं हूं