9

मुझे डरावनी हीरा समस्या के साथ कठिन समय हो रहा है। एक चेतावनी के लिए, यहाँ इस समस्या के शास्त्रीय वर्ग पदानुक्रम है:वर्चुअल विरासत और डरावना हीरा

B 
/\ 
C1 C2 
    \/
    D 

इसे हल करने के लिए, मानक समाधान C1 और C2 आभासी विरासत का उपयोग बी

से

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

 PureVirtualBase(SDK) 
      | 
     Base(SDK) 
    /  \ 
SubClassA SubClassB(SDK) 
     \  /
      Leaf 
ऐसी स्थिति जहां SubClassB बेस से आभासी विरासत उपयोग करने के लिए बदला नहीं जा सकता में

। कैसे क्या करना चाहिए ताकि:

  • पत्ता उदाहरण केवल एक बेस शामिल
  • जब PureVirtualBase में शुद्ध आभासी परिभाषित और बेस में लागू पहुँच कार्यों की कोशिश कर रहा अस्पष्टता से बचें
class PureVirtualBase 
{ 
public: 
    PureVirtualBase() 
    { 
     cout<<"<<PureVirtualBase::PureVirtualBase" << endl; 
     cout<<">>PureVirtualBase::PureVirtualBase" << endl; 
    } 
    virtual int f_PureVirtualBase()=0; 
}; 
class Base : public PureVirtualBase 
{ 
public: 
    Base(std::string id) { 
     cout<<"<<Base::Base:"<<id << endl; 
     m_id=id; 
     cout<<">>Base::Base:"<<m_id << endl; 
    } 
    virtual int f_PureVirtualBase() { 
     cout<<"Base::f_PureVirtualBase" << endl; 
     return 1; 
    } 
private: 
    std::string m_id; 
}; 
class SubClassA: public virtual Base 
{ 
public: 
    SubClassA(): Base("From SubClassA") { 
     cout<<"<<SubClassA::SubClassA" << endl; 
     cout<<">>SubClassA::SubClassA" << endl; 
    } 
}; 
class SubClassB: public Base 
{ 
public: 
    SubClassB():Base("From SubClassB") { 
     cout<<"<<SubClassB::SubClassB" << endl; 
     cout<<">>SubClassB::SubClassB" << endl; 
    } 
};  
class Leaf: public SubClassA, public SubClassB 
{ 
public: 
    Leaf():SubClassA(), SubClassB(), Base("From Leaf") { 
     cout << "<<Leaf::Leaf" << endl; 
     cout << ">>Leaf::Leaf"<< endl; 
    } 
}; 
int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    Leaf myleaf; 
    myleaf.f_PureVirtualBase(); 
    return a.exec(); 
} 
  • मैं कॉल टिप्पणी यह ​​संकलित f_PurevirtualBase लिए लेकिन मैं एक चेतावनी है कि आभासी आधार 'बेस' 'पत्ता' में दुर्गम कारण अस्पष्टता लिए अगर मैं इस कॉल uncomment हैं: मैं इस त्रुटि मिलती है: सदस्य के लिए अनुरोध ' f_PureVirtualBase 'अस्पष्ट
  • अगर मैं वर्ग के नाम (myleaf.SubClassA :: f_PureVirtualBase() तो यह काम करता है के द्वारा इस कॉल उपसर्ग है, लेकिन कुछ स्पष्ट रूप से गलत है के रूप में वहाँ 2 बेसपत्ता में निहित हैं ऑब्जेक्ट)।

कोई संकेत?

अधिक जानकारी टिप्पणियां जवाब देने के लिए

मेरे लक्ष्य वास्तुकला है थोड़ा और अधिक जटिल है कि नमूना मैं मूल प्रश्न में उपलब्ध कराई गई:

PureVirtualBase(SDK) 
     | 
    Base(SDK) 
     | 
     --SubClassA 
     --SubClassB(SDK) 
     --SubClassC(SDK) 
     --SubClassD(SDK) 

LeafOne: SubClassA और SubClassB (SDK) से विरासत

LeafTwo: सबक्लास और सबक्लास (एसडीके) से विरासत

LeafThree: SubClassA और SubClassD (एसडीके) से विरासत

SubClassA मेरा निजी कोड है। यह कस्टम कार्यों प्रदान करता है। इसे एसडीके विधियों द्वारा आधार उदाहरण की तरह माना जा सकता है। इस कक्षा को तत्काल नहीं किया जाएगा, लेकिन यह कुछ उपचार करने के दौरान ही LeafOne, LeafTwo और LeafThree को संभालने में सक्षम होने के लिए है।

+6

कैसे एक वर्ग विरासत में मिला और एक और समग्र। – iammilind

+2

यह कुछ है जो मैं विचार कर रहा हूं लेकिन इस तरह के एक लीफ क्लास का एकीकरण हमारे एसडीके में सुरुचिपूर्ण नहीं होगा और कई अलग-अलग समस्याओं को हल करना होगा। फिर भी आप सही हैं, इस समस्या को हल करने का यह एक तरीका है, लेकिन मैं इसे बनाने के लिए एक रास्ता खोजना चाहता हूं हालांकि एसडीके सुविधाओं के साथ आसान एकीकरण के लिए विरासत। – Marc

+0

आपको क्यों लगता है कि 'सबक्लास' को 'बेस' से उत्तराधिकारी होना चाहिए? 'SubClassB' की परिभाषा को देखते हुए यह स्पष्ट रूप से है कि 'बेस' को पदानुक्रम में वर्चुअल बेस क्लास के रूप में डिज़ाइन नहीं किया गया है जिसमें' SubClassB' शामिल है। –

उत्तर

4

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

विरासत ओओ भाषाओं में सबसे दुर्व्यवहार संरचनाओं में से एक है, यह एक समस्या का समाधान करता है, लेकिन इसे हर जगह golden hammer के रूप में उपयोग किया जाता है। आपके हाथ में कई बार screw है, नेल नहीं है और सही उपकरण हथौड़ा नहीं है।

+0

मुझे लगता है कि आप अभी बिंदु को हिट करते हैं। अंत में मैंने आपकी सलाह का उपयोग किया और हमारे वर्ग पदानुक्रम को बदल दिया। – Marc

+0

आपने यह हथौड़ा + स्क्रू मजाक भी कल कहा था, है ना? पी? – Liviu

1

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

पाठ्यक्रम का एक नुकसान यह है कि आपके पास उस प्रकार की पहचान नहीं है जिसे आप ढूंढ रहे हैं (उपclass सी 1 या सी 2 के "आईएसए" को संतुष्ट नहीं करेगा) जो इस दृष्टिकोण को पानी से बाहर करने के लिए पर्याप्त हो सकता है ।

यह सुंदर नहीं है। लेकिन मुझे उम्मीद है कि आपकी बाधाओं को देखते हुए यह "कम से कम खराब" समाधान हो सकता है।

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