साझा सामान्य पूर्वज के साथ C ++ कई विरासत को कैसे संभालता है?


13

मैं सी ++ लड़का नहीं हूं, लेकिन मैं इस बारे में सोचने के लिए मजबूर हूं। C ++ में एकाधिक वंशानुक्रम क्यों संभव है, लेकिन C # में नहीं? (मुझे हीरे की समस्या के बारे में पता है , लेकिन यह मैं यहां नहीं पूछ रहा हूं)। C ++ कई बेस कक्षाओं से विरासत में मिली समान विधि हस्ताक्षरों की अस्पष्टता को कैसे हल करता है? और उसी डिज़ाइन को C # में शामिल क्यों नहीं किया गया है?


3
संपूर्णता के लिए, "हीरे की समस्या" क्या है?
jcolebrand

1
@jcolebrand en.wikipedia.org/wiki/Multiple_inheritance डायमंड समस्या देखें
l46kok

1
निश्चित रूप से, मैंने इसे देखा, लेकिन मुझे कैसे पता चला कि संदीप का मतलब क्या है? यदि आप किसी अस्पष्ट नाम से कुछ संदर्भ देने जा रहे हैं, जब "एक साझा सामान्य पूर्वज के साथ एकाधिक उत्तराधिकार" अधिक प्रत्यक्ष है ...
jcolebrand

1
@jcolebrand मैंने इसे प्रतिबिंबित किया कि मुझे प्रश्न से क्या मिला। मुझे लगता है कि वह संदर्भ से विकिपीडिया पर संदर्भित हीरे की समस्या का मतलब है। अगली बार दोस्ताना टिप्पणी छोड़ें, और चमकदार नए सुझाए गए संपादन टूल का उपयोग करें :)
अर्लज़

1
@Earlz जो केवल तभी काम करता है जब मैं संदर्भ को समझता हूं। अन्यथा मैं एक बुरा संपादन कर रहा हूं, और यह सिर्फ बुरा जूजू है।
jcolebrand

जवाबों:


24

C ++ में एकाधिक वंशानुक्रम क्यों संभव है, लेकिन C # में नहीं?

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

और जब C # डिजाइन करते हुए मुझे लगता है कि उन्होंने जावा को देखा, तो देखा कि वास्तव में पूर्ण बहु विरासत में बहुत कुछ याद नहीं था और चीजों को सरल रखने के लिए चुना गया था।

C ++ कई बेस कक्षाओं से विरासत में मिली समान विधि हस्ताक्षरों की अस्पष्टता को कैसे हल करता है?

यह नहीं है । विशिष्ट आधार से बेस क्लास पद्धति को कॉल करने के लिए एक सिंटैक्स है, लेकिन केवल एक वर्चुअल विधि को ओवरराइड करने का कोई तरीका नहीं है और यदि आप उपवर्ग में विधि को ओवरराइड नहीं करते हैं, तो आधार को निर्दिष्ट किए बिना इसे कॉल करना संभव नहीं है कक्षा।

और उसी डिज़ाइन को C # में शामिल क्यों नहीं किया गया है?

इसमें शामिल करने के लिए कुछ भी नहीं है।


चूंकि जियोर्जियो ने टिप्पणियों में इंटरफ़ेस एक्सटेंशन विधियों का उल्लेख किया है, इसलिए मैं बताता हूं कि मिक्सिन क्या हैं और उन्हें विभिन्न भाषाओं में कैसे लागू किया जाता है।

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

mixin IComparable {
    public bool operator<(IComparable r) = 0;
    public bool operator>(IComparable r) { return r < this; }
    public bool operator<=(IComparable r) { return !(r < this); }
    public bool operator>=(IComparable r) { return !(r > this); }
    public bool operator==(IComparable r) { return !(r < this) && !(r > this); }
    public bool operator!=(IComparable r) { return r < this || r > this; }
};

पूर्ण वर्ग से अंतर यह है कि इसमें कोई भी डेटा सदस्य नहीं हो सकता है। इसे लागू करने के लिए कई विकल्प हैं। जाहिर है कई विरासत एक है। लेकिन कई विरासत को लागू करने के बजाय जटिल है। लेकिन यह वास्तव में यहाँ की जरूरत नहीं है। इसके बजाय, कई भाषाएं एक इंटरफ़ेस में मिक्सर को विभाजित करके इसे लागू करती हैं, जिसे कक्षा द्वारा लागू किया जाता है और विधि कार्यान्वयन का एक भंडार होता है, जिसे या तो कक्षा में ही इंजेक्ट किया जाता है या एक मध्यवर्ती आधार वर्ग उत्पन्न होता है और उन्हें वहां रखा जाता है। यह रूबी और डी में लागू किया गया है, जावा 8 में लागू किया जाएगा और इसे C ++ में मैन्युअल रूप से पुनरावृत्ति टेम्पलेट पैटर्न का उपयोग करके लागू किया जा सकता है । ऊपर, CRTP फॉर्म में, ऐसा दिखता है:

template <typename Derived>
class IComparable {
    const Derived &_d() const { return static_cast<const Derived &>(*this); }
public:
    bool operator>(const IComparable &r) const { r._d() < _d(); }
    bool operator<=(const IComparable &r) const { !(r._d() < _d(); }
    ...
};

और जैसे उपयोग किया जाता है:

class Concrete : public IComparable<Concrete> { ... };

यह नियमित आधार वर्ग होगा के रूप में आभासी घोषित किया जा करने के लिए कुछ भी करने की आवश्यकता नहीं है, इसलिए यदि टेम्पलेट में उपयोग किया जाता है उपयोगी अनुकूलन विकल्प खुला छोड़ देता है। ध्यान दें, कि C ++ में यह शायद अभी भी दूसरे माता-पिता के रूप में विरासत में मिला है, लेकिन ऐसी भाषाओं में जो एक से अधिक वंशानुक्रम की अनुमति नहीं देती हैं, यह एकल वंशानुक्रम श्रृंखला में डाली जाती है, इसलिए यह अधिक पसंद है

template <typename Derived, typename Base>
class IComparable : public Base { ... };
class Concrete : public IComparable<Concrete, Base> { ... };

संकलक कार्यान्वयन वर्चुअल प्रेषण से बच सकता है या नहीं भी हो सकता है।

C # में एक अलग कार्यान्वयन चुना गया था। C # में कार्यान्वयन पूरी तरह से अलग वर्ग के स्थिर तरीके हैं और विधि कॉल सिंटैक्स को कंपाइलर द्वारा उचित रूप से व्याख्या किया जाता है यदि दिए गए नाम की एक विधि मौजूद नहीं है, लेकिन एक "विस्तार विधि" परिभाषित है। इसका लाभ यह है कि विस्तार विधियों को पहले से संकलित वर्ग में जोड़ा जा सकता है और नुकसान यह है कि इस तरह के तरीकों को अनुकूलित संस्करण प्रदान करने के लिए उदासीन नहीं किया जा सकता है।


एक उल्लेख करना चाहते हैं कि इंटरफ़ेस विस्तार विधियों के साथ कई विरासत को जावा 8 में पेश किया जाएगा।
जियोर्जियो

@ जियोर्जियो: नहीं, जावा में कई विरासत निश्चित रूप से पेश नहीं की जाएंगी। मिक्सिंस होगा, जो कि बहुत अलग बात है, हालांकि यह कई उत्तराधिकार का उपयोग करने के लिए कई शेष कारणों को शामिल करता है और अधिकांश कारणों को उत्सुकता से आवर्ती टेम्पलेट पैटर्न (सीआरटीपी) का उपयोग करता है और ज्यादातर सीआरटीपी की तरह काम करता है, न कि कई विरासत की तरह।
Jan Hudec

मुझे लगता है कि एक वस्तु के बीच में कई उत्तराधिकारियों को संकेत की आवश्यकता नहीं होती है । यदि यह किया जाता है, तो कई इंटरफ़ेस वंशानुक्रम को भी इसकी आवश्यकता होगी।
svick

@ शविक: नहीं, यह नहीं है। लेकिन विकल्प बहुत कम कुशल है क्योंकि इसमें सदस्य के उपयोग के लिए आभासी प्रेषण की आवश्यकता होती है।
Jan Hudec

खदान की तुलना में बहुत अधिक पूर्ण उत्तर के लिए +1।
नाथन सी। ट्रेश

2

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

प्रतिनिधिमंडल विशेष रूप से नाम स्थान टकराव को संबोधित करता है: आप 5 वर्गों को सौंप सकते हैं और उनमें से सभी 5 अपने तरीके को प्रथम श्रेणी के सदस्यों के रूप में अपने दायरे में निर्यात करेंगे। बाहर इस पर कई विरासत में देख रहा है।


1
मुझे यह बहुत कम लगता है कि एमआई को C # में शामिल नहीं करने का यह प्राथमिक कारण था। इसके अलावा, यह पोस्ट इस सवाल का जवाब नहीं देता है कि जब आप "नेमस्पेस क्लैश" नहीं करते हैं तो MI C ++ में क्यों काम करता है।
डॉक्टर ब्राउन 12

@DocBrown मैंने विज़ुअल स्टूडियो टीम में एमएस पर काम किया है और मैं आपको विश्वास दिलाता हूं कि कम से कम इस कारण से कि वे प्रतिनिधिमंडल और इंटरफेस विकसित कर चुके हैं, नामपट्ट टकराव से पूरी तरह से बचने के लिए। प्रश्न की गुणवत्ता के रूप में, meh। अपने नीच का उपयोग करें, दूसरों को लगता है कि यह उपयोगी है।
नाथन सी। ट्रेश

1
जब से मुझे लगता है कि यह सही है, मुझे आपके जवाब को नीचा दिखाने का कोई इरादा नहीं है। लेकिन आपका उत्तर बताता है कि एमआई C ++ में पूरी तरह से अनुपयोगी है, और यही कारण है कि उन्होंने इसे C # में पेश नहीं किया। हालाँकि मुझे C ++ में MI बहुत पसंद नहीं है, लेकिन मुझे लगता है कि यह पूरी तरह से अनुपयुक्त नहीं है ।
डॉक्टर ब्राउन

1
यह एक कारण है, और मेरा मतलब यह नहीं था कि यह कभी काम नहीं करता है। जब कुछ गणना में गैर-नियतात्मक होता है, तो मैं कहता हूं कि यह "टूटा हुआ" है, या यह कि यह "काम नहीं करता है" जब मेरा मतलब है "यह वूडू की तरह है, तो यह काम कर सकता है या नहीं कर सकता है, अपनी मोमबत्तियां जलाएं और प्रार्थना करें।" : डी
नाथन सी। ट्रेस

1
"नेमस्पेस टकराव" गैर-नियतात्मक हैं?
डॉक्टर ब्राउन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.