मुझे C ++ में एकाधिक उत्तराधिकार से क्यों बचना चाहिए?


167

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

जवाबों:


259

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

सारांश

  1. वंशानुक्रम के बजाय सुविधाओं की संरचना पर विचार करें
  2. डर के हीरे से सावधान रहें
  3. वस्तुओं के बजाय कई इंटरफेस की विरासत पर विचार करें
  4. कभी-कभी, एकाधिक वंशानुक्रम सही बात है। अगर ऐसा है, तो इसका इस्तेमाल करें।
  5. कोड समीक्षाओं में अपने कई-विरासत वाले वास्तुकला की रक्षा के लिए तैयार रहें

1. शायद रचना?

यह विरासत के लिए सच है, और इसलिए, यह कई विरासत के लिए और भी अधिक सच है।

क्या आपकी वस्तु को वास्तव में दूसरे से विरासत में प्राप्त करने की आवश्यकता है? A Carको किसी Engineकार्य से विरासत की आवश्यकता नहीं है , न ही a से Wheel। A Carकी Engineचार और एक है Wheel

यदि आप रचना के बजाय इन समस्याओं को हल करने के लिए कई विरासत का उपयोग करते हैं, तो आपने कुछ गलत किया है।

2. द डायमंड ऑफ ड्रेड

आमतौर पर, आपके पास एक वर्ग होता है A, Bऔर फिर Cदोनों को विरासत में मिलता है A। और (मुझे मत पूछो क्यों) किसी ने फिर फैसला किया कि Dदोनों से विरासत में मिला होगा Bऔर C

मैंने 8 बार आठ साल में इस तरह की समस्या का सामना किया है, और यह देखने के लिए बहुत खुश है:

  1. शुरुआत से ही इसमें कितनी गलती थी (दोनों मामलों में, Dदोनों से विरासत में नहीं मिला होना चाहिए Bऔर C), क्योंकि यह खराब आर्किटेक्चर था (वास्तव में, Cइसका अस्तित्व ही नहीं होना चाहिए था ...)
  2. कितना देखरेख कि के लिए भुगतान कर रहे थे, क्योंकि C ++, माता पिता के वर्ग Aअपने पोते के वर्ग में मौजूद दो बार था D, और इस तरह, एक माता पिता क्षेत्र को अद्यतन करने के A::fieldलिए या तो मतलब यह दो बार अद्यतन करने (के माध्यम से B::fieldऔर C::field), या कुछ चुपचाप गलत और दुर्घटना जाना है, बाद में (नए सूचक में B::fieldऔर हटाएं C::field...)

C ++ में कीवर्ड वर्चुअल का उपयोग करके वंशानुक्रम को अर्हता प्राप्त करने के लिए ऊपर वर्णित दोहरे लेआउट से बचा जाता है यदि आप ऐसा नहीं चाहते हैं, लेकिन वैसे भी, मेरे अनुभव में, आप शायद कुछ गलत कर रहे हैं ...

ऑब्जेक्ट पदानुक्रम में, आपको पदानुक्रम को ट्री के रूप में रखने की कोशिश करनी चाहिए (एक नोड में एक माता-पिता हैं), ग्राफ़ के रूप में नहीं।

डायमंड के बारे में और अधिक (2017-05-03 को संपादित करें)

C ++ में डायमंड ऑफ ड्रेड के साथ वास्तविक समस्या ( डिजाइन ध्वनि है - क्या आपके कोड की समीक्षा की गई है! ), यह है कि आपको एक विकल्प बनाने की आवश्यकता है :

  • क्या कक्षा के Aलिए आपके लेआउट में दो बार मौजूद होना वांछनीय है , और इसका क्या मतलब है? यदि हाँ, तो हर तरह से इसे दो बार विरासत में मिला है।
  • यदि यह केवल एक बार मौजूद होना चाहिए, तो वस्तुतः इससे विरासत में मिला।

यह विकल्प समस्या के लिए अंतर्निहित है, और सी ++ में, अन्य भाषाओं के विपरीत, आप वास्तव में इसे हठधर्मिता के बिना अपने डिजाइन को भाषा के स्तर पर मजबूर कर सकते हैं।

लेकिन सभी शक्तियों की तरह, उस शक्ति के साथ जिम्मेदारी आती है: क्या आपके डिजाइन की समीक्षा की गई है।

3. इंटरफेस

शून्य या एक ठोस वर्गों की कई विरासत, और शून्य या अधिक इंटरफेस आमतौर पर ठीक है, क्योंकि आप ऊपर वर्णित भय के डायमंड का सामना नहीं करेंगे। वास्तव में, यह जावा में चीजों को कैसे किया जाता है।

आमतौर पर, जब आपका मतलब होता है जब C से विरासत में मिलता है Aऔर Bयह है कि उपयोगकर्ता इसका उपयोग कर सकते हैं Cजैसे कि यह एक था A, और / या जैसे कि यह एक था B

C ++ में, एक इंटरफ़ेस एक सार वर्ग है जिसमें है:

  1. इसकी सभी विधि को शुद्ध आभासी (= 0 से प्रत्यय) घोषित किया गया (2017-05-03 को हटा दिया गया)
  2. कोई सदस्य चर नहीं

शून्य से एक वास्तविक वस्तु की कई विरासत, और शून्य या अधिक इंटरफेस को "बदबूदार" नहीं माना जाता है (कम से कम, बहुत अधिक नहीं)।

C ++ सार इंटरफ़ेस के बारे में और अधिक (2017-05-03 संपादित करें)

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

दूसरा, C ++ में, यह वस्तुतः अमूर्त इंटरफेस से विरासत में मिलता है, (अतिरिक्त लागत / अप्रत्यक्ष के साथ भी)। यदि आप नहीं करते हैं, और इंटरफ़ेस वंशानुक्रम आपकी पदानुक्रम में कई बार दिखाई देता है, तो आपके पास अस्पष्टताएँ होंगी।

तीसरा, वस्तु उन्मुखीकरण महान है, लेकिन यह नहीं है केवल सच्चाई का पता वहाँ टीएम में सी ++। सही उपकरणों का उपयोग करें, और हमेशा याद रखें कि आपके पास C ++ में अन्य प्रतिमान हैं जो विभिन्न प्रकार के समाधान पेश करते हैं।

4. क्या आपको वास्तव में मल्टीपल इनहेरिटेंस की जरूरत है?

कभी कभी हाँ।

आमतौर पर, अपने Cवर्ग से इनहेरिट है Aऔर B, और Aऔर Bकर रहे हैं दो असंबंधित वस्तुओं (यानी इसी पदानुक्रम नहीं, आम, अलग अवधारणाओं, आदि में कुछ भी नहीं)।

उदाहरण के लिए, आपके पास NodesX, Y, Z निर्देशांक की एक प्रणाली हो सकती है , जो बहुत सारे ज्यामितीय गणना करने में सक्षम है (शायद एक बिंदु, ज्यामितीय वस्तुओं का हिस्सा) और प्रत्येक नोड एक स्वचालित एजेंट है, जो अन्य एजेंटों के साथ संवाद करने में सक्षम है।

शायद आपके पास पहले से ही दो पुस्तकालयों तक पहुंच है, प्रत्येक अपने स्वयं के नामस्थान (नामस्थान का उपयोग करने का एक और कारण ... लेकिन आप नामस्थान का उपयोग करते हैं, क्या आप नहीं?), एक जा रहा है geoऔर दूसरा?ai

तो तुम own::Nodeदोनों से ai::Agentऔर अपने खुद के व्युत्पन्न है geo::Point

यह वह क्षण है जब आपको खुद से पूछना चाहिए कि क्या आपको इसके बजाय रचना का उपयोग नहीं करना चाहिए। यदि own::Nodeवास्तव में दोनों एक ai::Agentऔर एक है geo::Point, तो रचना नहीं करेगी।

फिर आपको own::Node3 डी स्थान में उनकी स्थिति के अनुसार अन्य एजेंटों के साथ संवाद करने के लिए, कई विरासत की आवश्यकता होगी ।

(आप कि ध्यान दें जाएगा ai::Agentऔर geo::Pointपूरी तरह से, पूरी तरह से, पूरी तरह से संबंधित नहीं हैं ... यह काफी एकाधिक वंशानुक्रम के खतरे को कम करता है)

अन्य मामले (2017-05-03 संपादित करें)

अन्य मामले हैं:

  • कार्यान्वयन विस्तार के रूप में (उम्मीद है कि निजी) विरासत का उपयोग करना
  • कुछ सी ++ मुहावरों की तरह नीतियां कई विरासत का उपयोग कर सकती हैं (जब प्रत्येक भाग को दूसरों के माध्यम से संवाद करने की आवश्यकता होती है this)
  • आभासी विरासत से std :: अपवाद ( क्या अपवादों के लिए आभासी विरासत आवश्यक है? )
  • आदि।

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

5. तो, क्या मुझे मल्टीपल इनहेरिटेंस करना चाहिए?

ज्यादातर समय, मेरे अनुभव में, नहीं। एमआई सही उपकरण नहीं है, भले ही यह काम करने लगता है, क्योंकि इसका उपयोग आलसी द्वारा ढेर सुविधाओं के साथ मिलकर परिणामों को साकार किए बिना किया जा सकता है (जैसे कि Carदोनों को एक Engineऔर एक बनाकर Wheel)।

लेकिन कभी-कभी, हाँ। और उस समय, एमआई से बेहतर कुछ भी काम नहीं करेगा।

लेकिन क्योंकि MI बदबूदार है, कोड की समीक्षा में अपनी वास्तुकला का बचाव करने के लिए तैयार रहें (और इसका बचाव करना अच्छी बात है, क्योंकि यदि आप इसका बचाव करने में सक्षम नहीं हैं, तो आपको ऐसा नहीं करना चाहिए)।


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

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

" क्योंकि आप ऊपर वर्णित भय के हीरे का सामना नहीं करेंगे। " क्यों नहीं?
जिज्ञासु

1
मैं पर्यवेक्षक पैटर्न के लिए एमआई का उपयोग करता हूं।
कैलमेरियस ऑग

13
@ बिलक: बेशक यह आवश्यक नहीं है। यदि आपके पास एमआई के बिना एक टर्निंग पूर्ण भाषा है, तो आप एमआई के साथ कोई भी भाषा कर सकते हैं। तो हाँ, यह आवश्यक नहीं है। कभी। उस ने कहा, यह एक बहुत ही उपयोगी उपकरण हो सकता है, और तथाकथित खूंखार हीरा ... मैं वास्तव में कभी नहीं समझ पाया कि "खूंखार" शब्द क्यों है। यह वास्तव में काफी आसान है, क्योंकि यह आमतौर पर समस्या का कारण नहीं है।
थॉमस ईडिंग

145

बज़्ने स्ट्रॉस्ट्रप के साथ एक साक्षात्कार से :

लोग काफी सही ढंग से कहते हैं कि आपको कई विरासतों की आवश्यकता नहीं है, क्योंकि कुछ भी आप कई विरासतों के साथ कर सकते हैं जो आप एकल विरासत के साथ भी कर सकते हैं। आप सिर्फ मेरे द्वारा उल्लेखित प्रतिनिधि ट्रिक का उपयोग करते हैं। इसके अलावा, आपको किसी भी तरह की विरासत की आवश्यकता नहीं है, क्योंकि आप एकल विरासत के साथ जो कुछ भी करते हैं वह आप वर्ग के माध्यम से अग्रेषित करके विरासत के बिना भी कर सकते हैं। वास्तव में, आपको किसी भी वर्ग की आवश्यकता नहीं है, क्योंकि आप यह सभी बिंदुओं और डेटा संरचनाओं के साथ कर सकते हैं। लेकिन आप ऐसा क्यों करना चाहेंगे? भाषा सुविधाओं का उपयोग करना कब सुविधाजनक है? आप वर्कअराउंड कब पसंद करेंगे? मैंने ऐसे मामले देखे हैं जहाँ कई उत्तराधिकार उपयोगी हैं, और मैंने ऐसे मामले भी देखे हैं जहाँ कई जटिल बहु विरासतें उपयोगी हैं। आम तौर पर, मैं वर्कअराउंड करने के लिए भाषा द्वारा दी जाने वाली सुविधाओं का उपयोग करना पसंद करता हूं


6
C ++ की कुछ विशेषताएं हैं जो मैंने C # और Java में मिस की हैं, हालांकि उनके होने से डिज़ाइन अधिक कठिन / जटिल हो जाएगा। उदाहरण के लिए, अपरिवर्तनीयता की गारंटी const- मुझे क्लूनी वर्कआर्ड (आमतौर पर इंटरफेस और रचना का उपयोग करके) लिखना पड़ता है जब एक वर्ग को वास्तव में परस्पर-और अपरिवर्तनीय होने की आवश्यकता होती है। हालाँकि, मैंने कभी भी एक से अधिक उत्तराधिकार प्राप्त करने से नहीं चूके हैं, और मुझे कभी नहीं लगा कि इस सुविधा की कमी के कारण मुझे वर्कअराउंड लिखना पड़ा। यही अंतर है। हर मामले में मैंने कभी देखा है, एमआई का उपयोग नहीं करना बेहतर डिजाइन विकल्प है, न कि वर्कअराउंड।
ब्लूराजा - डैनी पफ्लुघोफ्ट

24
+1: सही उत्तर: यदि आप इसका उपयोग नहीं करना चाहते हैं, तो इसका उपयोग न करें।
थॉमस ईडिंग

38

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

मौत का सबसे बड़ा हीरा:

class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;

अब आपके पास बाल के भीतर ग्रैंडपैरेंट की दो "प्रतियां" हैं।

C ++ ने इसके बारे में सोचा है और आपको मुद्दों के इर्द-गिर्द आने के लिए आभासी विरासत करने की सुविधा देता है।

class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;

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


21
और यदि आप विरासत पर प्रतिबंध लगाते हैं और केवल इसके बजाय रचना का उपयोग करते हैं, तो आपके पास हमेशा दो ही होते GrandParentहैं Child। एमआई का डर है, क्योंकि लोगों को लगता है कि वे भाषा के नियमों को नहीं समझ सकते हैं। लेकिन जो कोई भी इन सरल नियमों को प्राप्त नहीं कर सकता है वह एक गैर तुच्छ कार्यक्रम नहीं लिख सकता है।
जिज्ञासु

1
यह कठोर लगता है, सी ++ नियम सभी दौर बहुत विस्तृत हैं। ठीक है, इसलिए भले ही व्यक्तिगत नियम सरल हों, उनमें से कई ऐसे हैं, जो पूरी बात को सरल नहीं बनाते हैं, कम से कम किसी इंसान के अनुसरण के लिए।
ज़ेब्राफिश

11

देखें: एकाधिक वंशानुक्रम

एकाधिक विरासत को आलोचना मिली है और इस तरह, कई भाषाओं में लागू नहीं किया गया है। आलोचनाओं में शामिल हैं:

  • जटिलता बढ़ गई
  • शब्दार्थ अस्पष्टता को अक्सर हीरे की समस्या के रूप में संक्षेपित किया जाता है
  • एक ही वर्ग से कई बार स्पष्ट रूप से विरासत में नहीं मिल रहा है
  • वंशानुक्रम बदलने का क्रम वर्ग शब्दार्थ।

C ++ / Java स्टाइल कंस्ट्रक्टर्स वाली भाषाओं में मल्टीपल इनहेरिटेंस, कंस्ट्रक्टर्स और कंस्ट्रक्टर चाइनिंग की विरासत की समस्या को बढ़ाता है, जिससे इन भाषाओं में रखरखाव और एक्स्टेंसिबिलिटी की समस्या पैदा होती है। बहुत अलग-अलग निर्माण विधियों के साथ वंशानुगत रिश्तों में ऑब्जेक्ट्स को निर्माण प्रतिमान के तहत लागू करना कठिन है।

COM और जावा इंटरफ़ेस जैसे इंटरफ़ेस (शुद्ध सार वर्ग) का उपयोग करने के लिए इसे हल करने का आधुनिक तरीका।

मैं इसके स्थान पर अन्य काम कर सकता हूं?

हाँ तुम कर सकते हो। मैं GoF से चोरी करने जा रहा हूं ।

  • एक अंतरफलक के लिए कार्यक्रम, एक कार्यान्वयन नहीं
  • वंशानुक्रम पर रचना को प्राथमिकता दें

8

सार्वजनिक विरासत एक आईएस-ए संबंध है, और कभी-कभी एक वर्ग कई अलग-अलग वर्गों का एक प्रकार होगा, और कभी-कभी यह प्रतिबिंबित करना महत्वपूर्ण होता है।

"मिक्सिन्स" कभी-कभी उपयोगी भी होते हैं। वे आम तौर पर छोटे वर्ग हैं, आमतौर पर कुछ भी विरासत में नहीं मिलता है, उपयोगी कार्यक्षमता प्रदान करता है।

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

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


6

आपको एकाधिक उत्तराधिकार से "बचना" नहीं चाहिए, लेकिन आपको ऐसी समस्याओं के बारे में पता होना चाहिए जो 'हीरा समस्या' ( http://en.wikipedia.org/wiki/Diamond_problem ) के रूप में उत्पन्न हो सकती हैं और देखभाल के साथ आपको दी गई शक्ति का इलाज कर सकती हैं , जैसा कि आपको सभी शक्तियों के साथ होना चाहिए।


1
+1: जिस तरह आपको पॉइंटर्स से बचना नहीं चाहिए; आपको बस उनके प्रभाव के बारे में पता होना चाहिए। लोगों को मुहावरों को बंद करने की ज़रूरत है (जैसे "एमआई बुराई है", "न ऑप्टिमाइज़ करें", "गोटो बुराई है") उन्होंने इंटरनेट से सिर्फ इसलिए सीखा क्योंकि कुछ हिप्पी ने कहा कि यह उनकी स्वच्छता के लिए बुरा था। सबसे बुरी बात यह है कि उन्होंने कभी भी इस तरह की चीजों का इस्तेमाल करने की कोशिश नहीं की और बस इसे ऐसे लिया जैसे कि बाइबल से बोला गया हो।
थॉमस ईडिंग

1
मैं सहमत हूँ। इसे "टाल" न दें, लेकिन समस्या को हल करने का सबसे अच्छा तरीका पता है। हो सकता है कि मैं कंपोजिटल विशेषता का उपयोग करूं, लेकिन C ++ में ऐसा नहीं है। शायद मैं बल्कि स्वचालित प्रतिनिधिमंडल के 'हैंडल' का उपयोग करूंगा, लेकिन C ++ में ऐसा नहीं है। तो मैं कई अलग-अलग उद्देश्यों के लिए एमआई के सामान्य और कुंद टूल का उपयोग करता हूं, शायद एक साथ।
JDługosz

3

थोड़ा सार होने के जोखिम पर, मुझे श्रेणी सिद्धांत के फ्रेम के भीतर विरासत के बारे में सोचने के लिए रोशन लगता है।

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

A --> B

इसका मतलब है कि से class Bप्राप्त होता है class A। ध्यान दें, दिया गया

A --> B, B --> C

हम कहते हैं कि C, B से व्युत्पन्न है जो A से प्राप्त होता है, इसलिए C को A से व्युत्पन्न भी कहा जाता है

A --> C

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

यह थोड़ा सा सेटअप है, लेकिन इसके साथ आइए एक नजर डालते हैं हमारे डायमंड ऑफ डूम पर:

C --> D
^     ^
|     |
A --> B

यह एक छायादार आरेख है, लेकिन यह करूँगा। इसलिए , और , Dसभी से विरासत में मिला है । इसके अलावा, और ओपी के प्रश्न को संबोधित करने के करीब पहुंचना भी किसी भी सुपरक्लास से विरासत में मिला है । हम एक चित्र बना सकते हैंABCDA

C --> D --> R
^     ^
|     |
A --> B
^ 
|
Q

अब, समस्याओं की मौत डायमंड के साथ जुड़े यहाँ जब कर रहे हैं Cऔर Bसाझा कुछ संपत्ति / विधि के नाम और चीजें अस्पष्ट मिलता है, हालाँकि, यदि हम किसी साझा व्यवहार को आगे Aबढ़ाते हैं तो अस्पष्टता गायब हो जाती है।

स्पष्ट शब्दों में कहें, हम चाहते हैं A, Bऔर Cऐसा होना चाहिए कि अगर Bऔर उसके बाद Cसे विरासत में उपवर्ग के रूप में फिर से लिखा जा सके । यह एक पुशआउट नामक कुछ बनाता है ।QAQA

पुलबैकD नामक एक सममित निर्माण भी है । यह अनिवार्य रूप से सबसे सामान्य उपयोगी वर्ग है जिसे आप निर्माण कर सकते हैं जो दोनों से विरासत में मिला है और । यही है, अगर आपके पास कोई अन्य वर्ग है, जो बहुतायत से विरासत में मिला है , और फिर एक ऐसा वर्ग है जहां उपवर्ग के रूप में फिर से लिखा जा सकता है ।BCRBCDRD

यह सुनिश्चित करना कि हीरे की आपकी युक्तियां पुलबैक और पुशआउट हैं, हमें नाम-क्लैशिंग या रखरखाव के मुद्दों को संभालने का एक अच्छा तरीका प्रदान करती हैं जो अन्यथा उत्पन्न हो सकती हैं।

नोट पारसेबल के उत्तर से यह प्रेरित है क्योंकि उनकी सलाह ऊपर दिए गए मॉडल द्वारा दी गई है कि हम पूरी श्रेणी के सभी संभावित वर्गों में काम करते हैं।

मैं उनके तर्क को कुछ सामान्य करना चाहता था, जिससे पता चलता है कि कई विरासत वाले रिश्ते कितने शक्तिशाली और गैर-समस्याग्रस्त हो सकते हैं।

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


3

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

हमारे लिए, एफिल का उपयोग करते हुए, एमआई कुछ और के रूप में प्राकृतिक है और टूलबॉक्स में एक और ठीक उपकरण है। सच कहूँ, हम काफी असंबद्ध हैं कि कोई और एफिल का उपयोग नहीं कर रहा है। कोई चिंता नहीं। हम खुश हैं कि हमारे पास क्या है और आपको एक नज़र रखने के लिए आमंत्रित करते हैं।

जब आप देख रहे हों: शून्य-सुरक्षा और नल पॉइंटर डेरेफेरेंसिंग के उन्मूलन पर विशेष ध्यान दें। जब हम एमआई के चारों ओर नृत्य कर रहे हैं, तो आपके संकेत खो रहे हैं! :-)


2

प्रत्येक प्रोग्रामिंग भाषा में पेशेवरों और विपक्षों के साथ ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग का थोड़ा अलग उपचार होता है। C ++ का संस्करण प्रदर्शन पर जोर देता है और इसका नकारात्मक पक्ष यह है कि यह अमान्य कोड लिखना मुश्किल है - और यह कई उत्तराधिकार का सच है। एक परिणाम के रूप में वहाँ इस सुविधा से दूर प्रोग्रामर चलाने की प्रवृत्ति है।

अन्य लोगों ने इस सवाल को संबोधित किया है कि बहु विरासत क्या अच्छा नहीं है। लेकिन हमने बहुत कम टिप्पणियां देखी हैं, जो कम-से-कम इसका मतलब है कि इससे बचने का कारण यह है कि यह सुरक्षित नहीं है। खैर, हाँ और नहीं।

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

class CounterMixin {
    int count;
public:
    CounterMixin() : count( 0 ) {}
    virtual ~CounterMixin() {}
    virtual void increment() { count += 1; }
    virtual int getCount() { return count; }
};

class Foo : public Bar, virtual public CounterMixin { ..... };

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

ध्यान दें कि यहां "मिक्स-इन" शब्द का उपयोग पैरामीटराइज्ड टेम्प्लेट क्लास ( अच्छी व्याख्या के लिए इस लिंक को देखें ) के समान नहीं है, लेकिन मुझे लगता है कि यह शब्दावली का उचित उपयोग है।

अब मैं यह धारणा नहीं देना चाहता कि सुरक्षित रूप से एकाधिक विरासत का उपयोग करने का यही एकमात्र तरीका है। यह सिर्फ एक ही तरीका है जो जांचना काफी आसान है।


2

आपको इसका उपयोग सावधानी से करना चाहिए, कुछ मामले हैं, जैसे डायमंड प्रॉब्लम , जब चीजें जटिल हो सकती हैं।

वैकल्पिक शब्द
(स्रोत: learncpp.com )


12
यह एक बुरा उदाहरण है, क्योंकि एक कापियर को स्कैनर और प्रिंटर से बना होना चाहिए, न कि उनसे विरासत में।
Svante

2
वैसे भी, ए Printerभी नहीं होना चाहिए PoweredDevice। A Printerमुद्रण के लिए है, न कि बिजली प्रबंधन के लिए। किसी विशेष प्रिंटर के कार्यान्वयन के लिए कुछ बिजली प्रबंधन करना पड़ सकता है, लेकिन इन बिजली प्रबंधन आदेशों को सीधे प्रिंटर के उपयोगकर्ताओं के सामने उजागर नहीं किया जाना चाहिए। मैं इस पदानुक्रम के किसी भी वास्तविक विश्व उपयोग की कल्पना नहीं कर सकता।
जिज्ञासु


1

हीरे के पैटर्न से परे, कई उत्तराधिकार वस्तु मॉडल को समझने में कठिन बनाते हैं, जिससे रखरखाव लागत बढ़ जाती है।

रचना आंतरिक रूप से समझने, समझने और समझाने में आसान है। यह कोड लिखने के लिए थकाऊ हो सकता है, लेकिन एक अच्छा आईडीई (यह कुछ साल रहा है जब मैंने विजुअल स्टूडियो के साथ काम किया है, लेकिन निश्चित रूप से जावा आईडीई सभी के पास महान रचना शॉर्टकट स्वचालित उपकरण हैं) आपको उस बाधा से उबरना चाहिए।

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

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


what happens when the designer for 'B' adds a 'makeJuice' method which generates and electrical current?उह, आपको पाठ्यक्रम की एक जटिल त्रुटि मिलती है (यदि उपयोग अस्पष्ट है)।
थॉमस ईडिंग

1

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

विशेष रूप से C ++ के लिए, सुविधा की प्रमुख कमजोरी कई वंशानुक्रम का वास्तविक उदाहरण नहीं है, लेकिन कुछ निर्माणों से यह अनुमति देता है कि वे लगभग हमेशा विकृत होते हैं। उदाहरण के लिए, एक ही वस्तु की कई प्रतियों को विरासत में देना जैसे:

class B : public A, public A {};

परिभाषा द्वारा विकृत है। अंग्रेजी में अनुवादित यह "बी एक ए और एक ए" है। तो, मानव भाषा में भी एक गंभीर अस्पष्टता है। क्या आपका मतलब है "B में 2 As हैं" या सिर्फ "B एक A" है। इस तरह के पैथोलॉजिकल कोड की अनुमति देने, और इसे एक उदाहरण के रूप में बदतर बनाने के बाद, C ++ को कोई एहसान नहीं हुआ जब यह उत्तराधिकारी भाषाओं में फीचर रखने के लिए एक मामला बनाने की बात आई।


0

आप वरीयता के लिए रचना का उपयोग कर सकते हैं।

सामान्य भावना यह है कि रचना बेहतर है, और यह बहुत अच्छी तरह से चर्चा की गई है।


4
-1: The general feeling is that composition is better, and it's very well discussed.इसका मतलब यह नहीं है कि रचना बेहतर है।
थॉमस एडिंग

इसे छोड़कर, वास्तव में, बेहतर है।
अली अफसर

12
उन मामलों को छोड़कर, जहां यह बेहतर नहीं है।
थॉमस एडिंग

0

इसमें प्रति वर्ग 4/8 बाइट्स शामिल हैं। (प्रति वर्ग एक सूचक)।

यह कभी भी चिंता का विषय नहीं हो सकता है, लेकिन अगर एक दिन आपके पास एक माइक्रो डेटा संरचना होती है जो कि अरबों समय का होता है तो यह होगा।


1
उस बारे में यकीन? आमतौर पर, किसी भी गंभीर वंशानुक्रम के लिए प्रत्येक कक्षा सदस्य में एक संकेतक की आवश्यकता होती है, लेकिन क्या यह जरूरी है कि विरासत में मिली कक्षाएं हों? इस बिंदु पर अधिक, आपके पास कितनी बार अरबों की डेटा संरचनाएँ हैं?
डेविड थॉर्नले

3
@DavidThornley " आपके पास कितनी बार अरबों की डेटा संरचनाएँ हैं? " जब आप MI के साथ बहस कर रहे हैं।
जिज्ञासु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.