2010-05-08 17 views
6

यह उत्पन्न करने वाला परिदृश्य काफी जटिल है इसलिए मैं कुछ टुकड़े निकाल दूंगा और शामिल वर्गों का सटीक प्रतिनिधित्व दूंगा।सी ++ एकाधिक विरासत प्रश्न

/* This is inherited using SI by many classes, as normal */ 
class IBase 
{ 
virtual string toString()=0; 
}; 

/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */ 
class Base2 
{ 
string toString() 
{ 
    ... 
} 
}; 

/* a special class, is this valid? */ 
class Class1 : public IBase, public Base2 
{ 
}; 

तो, क्या यह मान्य है? ToString पर संघर्ष होगा? या कक्षा 1 आईबीएएस को संतुष्ट करने के लिए बेस 2 :: टूस्ट्रिंग का उपयोग कर सकते हैं? जैसा कि मैंने कहा है कि कई अन्य चीजें नहीं दिखायी गई हैं, इसलिए इस उदाहरण पर प्रमुख डिज़ाइन परिवर्तनों के सुझाव शायद उपयोगी नहीं हैं ... हालांकि किसी भी सामान्य सुझाव/सलाह का स्वागत है।

मेरे अन्य विचार कुछ इस तरह था:

class Class1 : public IBase, public Base2 
{ 
virtual string toString() 
{ 
    return Base2::toString(); 
} 
}; 

यह बनाता है और लिंक है, लेकिन मुझे पता नहीं है अगर यह कीड़े छुप गई हैं।

उत्तर

2

आप इसे "आभासी विरासत" का उपयोग करके ठीक कर सकते हैं।

एक आम आधार वर्ग कि केवल को परिभाषित करता है एक शुद्ध आभासी toString विधि बनाने पर विचार करें, उदा (या वास्तव में, जो कुछ भी तरीकों में से शुद्ध आभासी संस्करण यह दोनों IBase और Base2 के लिए समझ में वाला राज्य बन गया) यह अभी भी क्योंकि Class1Stringable आधार के दो प्रतियां विरासत में मिला दिया जाएगा काम नहीं करेगा के रूप में यह है अब

class IBase : public Stringable 
{ 
}; 

class Base2 : public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

:

class Stringable { 
    public: 
    virtual string toString() = 0; 
}; 

फिर, इस Stringable वर्ग से दोनों IBase और Base2 इनहेरिट है कक्षा, जिसमें से केवल एक ही अपने विरासत पदानुक्रम में toString के लिए कार्यान्वयन है। इसे "dreaded diamond" के रूप में जाना जाता है। हालांकि, अगर IBase और Base2लगभग Stringable से वारिस के लिए गए थे, इस तरह:

class IBase : virtual public Stringable 
{ 
}; 

class Base2 : virtual public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

फिर इस संकलक कि वहाँ केवल एक सामान्य Stringable आधार वर्ग भले ही IBase और Base2 दोनों एक से प्राप्त होती हैं होना चाहिए बताता है कक्षा, जो वास्तव में आप चाहते हैं, क्योंकि Base2::toStringClass1 के लिए उपयोग किया जाता है।

आपके दूसरे विचार में कोई "छिपी हुई बग" नहीं है, लेकिन बट में दर्द का कुछ हद तक बार-बार लागू करने के लिए दर्द होता है, जैसा कि आप शायद महसूस करते हैं।

1

यह ठीक काम करना चाहिए।

आप ToString() की परिभाषा प्रदान करने के लिए आईबीएएस इंटरफ़ेस को ठीक से ओवरराइड कर रहे हैं जो Base2::ToString() तक फॉरवर्ड किया जाएगा।

ध्यान दें कि Base2 वर्चुअल के रूप में स्ट्रिंग() को घोषित नहीं करता है, इसलिए Class1Base2::ToString के व्यवहार को ओवरराइड नहीं कर सकता है। वहां कोई अस्पष्टता नहीं है।

और इसके अलावा, यह virtual inheritance द्वारा हल की गई एकाधिक विरासत में क्लासिक हीरे की समस्या नहीं है क्योंकि वे बेस क्लास साझा नहीं करते हैं।

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