2012-02-22 7 views
9

मैं सार कक्षाओं का उपयोग करके सी ++ में इंटरफ़ेस प्रकारों को परिभाषित करने और ठोस वर्गों के साथ कार्यान्वित करने की कोशिश कर रहा हूं। जिस समस्या में मैं दौड़ रहा हूं वह यह है कि मैं दूसरे इंटरफ़ेस से उत्तराधिकारी और इंटरफ़ेस दोनों नहीं कर सकता और बेस कंक्रीट क्लास से कार्यान्वयन का वारिस कर सकता हूं।विरासत कंक्रीट कक्षाओं के साथ सी ++ में इंटरफेस लागू करना

मेरा लक्ष्य इंटरफेस के पदानुक्रम को परिभाषित करने में सक्षम होना है जो कम जटिल आधार इंटरफेस से प्राप्त हो सकता है। मैं कंक्रीट कक्षाओं से विरासत में इंटरफेस के कार्यान्वयन को बढ़ाने में भी सक्षम होना चाहता हूं (जैसे नीचे दिए गए उदाहरण में TObjectA से विरासत)।

यह मेरे पास है। मुझे जो त्रुटि मिल रही है वह है "अमूर्त वर्ग प्रकार" TObjectB "की वस्तु की अनुमति नहीं है"। मेरा मानना ​​है कि मुझे पता है क्यों, ऐसा इसलिए है क्योंकि मैंने TOBjectB में MethodA() को लागू नहीं किया है। लेकिन मैं वास्तव में चाहता हूं कि बेस क्लास (TObjectA) द्वारा प्रदान किया गया कार्यान्वयन हो और अभी भी इंटरफ़ेस पदानुक्रम (IInterfaceA से IInterfaceB विरासत प्राप्त हो)। मैं अपने व्युत्पन्न कंक्रीट कक्षाओं में सभी विरासत इंटरफ़ेस विधियों को दोहराना नहीं चाहता हूं। मैं यह कैसे कर सकता हूँ?

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed 
    b->MethodB(); 
    delete b; 
} 
+2

आपको वर्चुअल बेस क्लास की आवश्यकता है। जैसे [यहां देखें] (http://stackoverflow.com/questions/4605556/when-virtual-inheritance-is-a-good-design/4606206#4606206) –

उत्तर

11

अपने वर्ग पदानुक्रम में, TObjectB वास्तव में दो IInterfaceA आधार वर्ग subobjects है: एक IInterfaceB और एक TObjectA के माध्यम से विरासत में मिला के माध्यम से विरासत में मिला। उनमें से प्रत्येक से MethodA() लागू करने की आवश्यकता है।

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : public virtual IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public virtual IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public virtual IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    TObjectB b_object; 
    IInterfaceB& b = b_object; 
    b.MethodB(); 
} 

या नहीं, इस तरह के जटिल वर्ग पदानुक्रम हैं:

आप सार्वजनिक आभासी विरासत है, जो यह सुनिश्चित करता है वहाँ केवल एक ही आधार वर्ग प्रत्येक इंटरफ़ेस वर्ग प्रकार के subobject है का उपयोग कर अंतरफलक वर्गों से विरासत की जरूरत है वांछनीय एक और मामला पूरी तरह से है।

+0

जब मैं आपके कोड का उपयोग करता हूं तो मुझे निम्न चेतावनी मिलती है "चेतावनी: ' TObjectB ': विरासत' TObjectA :: TObjectA :: MethodA 'प्रभुत्व के माध्यम से "। इसके अलावा जब मैं परीक्षण ढेर आवंटित वस्तुओं का उपयोग करने के बदलने मैं एक क्रम अभिकथन त्रुटि मिलती है और निष्पादन बंद हो जाता है: शून्य TestInterfaces() { IInterfaceB * ख = नए TObjectB(); बी-> विधि बी(); बी हटाएं; } – sysrpl

+0

यदि आपके पास उनके माध्यम से ऑब्जेक्ट को पॉलिमॉर्फिक रूप से हटाने का इरादा है तो आपके इंटरफ़ेस कक्षाओं में आभासी विनाशक होना चाहिए। चेतावनी के लिए: जटिल विरासत पदानुक्रम से बचें। –

1

आपकी समस्या भयभीत हीरा विरासत के कारण होती है। आपने TObjectA::IInterfaceA::MethodA लागू किया है लेकिन IInterfaceB::IInterfaceA::MethodA नहीं है।

मेरी सिफारिश IIterfaceA और IIterfaceB को पूरी तरह से स्वतंत्र बनाना होगा। यदि यह संभव नहीं है, तो आप आभासी विरासत में देख सकते हैं।