2012-04-24 13 views
10

मैं सिर्फ कोड के इस टुकड़े की कोशिश की है:एकाधिक वंशानुक्रम: 2Classes1Method

struct FaceOfPast 
{ 
    virtual void Smile() = 0; 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() = 0; 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

...

void main() 
{ 
    Janus* j = new Janus(); 
    FaceOfFuture* future = j; 
    FaceOfPast* past = j; 

    future->Smile(); 
    past->Smile(); 

    delete j; 
} 

यह इरादा (आउटपुट दो स्माइली चेहरे) के रूप में काम करता है, लेकिन मुझे नहीं पता लगता है कि इसे संकलित करना चाहिए, Smile()Janus में संदिग्ध होने के पुनर्विक्रय।

यह कैसे (और क्यों) काम करता है?

उत्तर

7

वहाँ कोई अस्पष्टता नहीं है क्योंकि आप FaceOfFuture और FaceOfPast की ओर इशारा है कि केवल एक विधि Smile() घोषित पर Smile() फोन है।

क्योंकि एक आधार वर्ग सूचक पर विधि कॉल करने में कोई अस्पष्टता में परिणाम नहीं कर सकते हैं, के स्थितियों जब आप सीधे बच्चे वर्ग सूचक पर विधि कॉल का इलाज करते हैं:

Janus* j = new Janus(); 
j->Smile(); 

व्युत्पन्न वर्ग, ओवरराइडिंग के अलावा, बेस क्लास की Smile() की घोषणा को भी छुपाता है।

निम्नलिखित compiles:

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

हालांकि आप एक Janus पर Smile फोन, आधार वर्ग घोषणाओं छिपे हुए हैं आप एक अस्पष्टता आप अपने व्युत्पन्न वर्ग में विधि अधिभावी नहीं होगा केवल तभी होगा । अस्पष्टता की वजह से

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
}; 

int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

:

निम्नलिखित नहीं करता है।

+2

प्रश्न कॉलिंग भाग के बारे में प्रतीत नहीं होता है, लेकिन पुनर्वितरण भाग: आप एक ही विधि को लिखकर 2 अलग-अलग वर्गों से 2 वर्चुअल विधियों को फिर से परिभाषित क्यों कर सकते हैं? – alexisdm

0
Janus* j = new Janus(); 
FaceOfFuture* future = j; 
FaceOfPast* past = j; 

कोड के इस खंड एक आधार वर्ग के लिए करने के लिए नीचे डाले। तो जब आप निम्नलिखित

future->Smile(); 
past->Smile(); 

यह वास्तव में फेसफॉस्ट और फेसऑफ्यूचर के लिए एक सूचक है।

1

सी ++ मानक (10.3.2) अनुसार:

एक आभासी सदस्य समारोह VF एक वर्ग बेस में और एक वर्ग व्युत्पन्न में घोषित किया जाता है, तो बेस से प्रत्यक्ष या परोक्ष रूप व्युत्पन्न , एक सदस्य समारोह एक ही नाम, पैरामीटर प्रकार सूची, सीवी-योग्यता, और बेस के रूप में रेफरी-क्वालीफायर (या उसी का अभाव) :: VF साथ VF घोषित किया जाता है, तो व्युत्पन्न :: VF [ ...] ओवरराइड बेस :: vf

वहाँ एकाधिक वंशानुक्रम के लिए कोई विशेष उपचार हो प्रतीत नहीं होता है, तो यह सबसे शायद यहाँ भी लागू होते हैं: कोई अस्पष्टता के बिना void Janus::Smile() ओवरराइड दोनों तरीकों, सिर्फ इसलिए कि यह दोनों आधार वर्ग के रूप में ठीक उसी नाम और हस्ताक्षर है तरीकों।

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