2013-08-23 12 views
8

मैं इस कोड की कोशिश की के साथ कई आधार वर्ग से विरासत:सी ++ एक ही वर्चुअल समारोह नाम

class A 
{ 
    virtual void foo() = 0; 
}; 

class B 
{ 
    virtual void foo() = 0; 
}; 

class C : public A, public B 
{ 
    //virtual void A::foo(){} 
    //virtual void B::foo(){} 

    virtual void A::foo(); 
    virtual void B::foo(); 
}; 

void C::A::foo(){} 
void C::B::foo(){} 

int main() 
{ 
    C c; 
    return 0; 
} 

यह ठीक है जब टिप्पणी की भाग का उपयोग कर, लेकिन जब मैं कक्षा घोषणा के बाहर परिभाषाओं लिखने की कोशिश, संकलक रिपोर्ट त्रुटियों। मैं MSVC11 संकलक उपयोग कर रहा हूँ, किसी को पता है कि यह कैसे लिखने के लिए? मुझे कोड को cpp फ़ाइल में ले जाने की आवश्यकता है।

आप ~~

+1

टिप्पणी की भाग भी जीसीसी में काम नहीं कर रहा: A::foo के लिए दो अलग-अलग ओवरराइड और विरासत की एक और परत शुरू करने से अन्य की तुलना में अलग व्यवहार के साथ B::foo के लिए कोई तरीका नहीं है। –

+2

यह बिल्कुल समझ में नहीं आता है। यह सिर्फ 'वर्चुअल शून्य foo();', और बस * एक बार * होना चाहिए। –

+0

कैसे आप _use_ को 'A',' b' और 'C' चाहते हो? वहाँ कई संभावनाएं हैं: [उदाहरण 1] (http://ideone.com/KlVTgv), [उदाहरण 2] (http: // ideone।कॉम/आर 2 एसईटीज़), ... (जो संभवतः आवश्यक से अधिक कार्यों को परिभाषित करते हैं) –

उत्तर

4

आप सिर्फ एक आभासी समारोह foo मिल गया है धन्यवाद:

class A { 
    virtual void foo() = 0; 
}; 

class B { 
    virtual void foo() = 0; 
}; 

class C : public A, public B { 
    virtual void foo(); 

}; 

void C::foo(){} 
void C::A::foo(){} 
void C::B::foo(){}; 

int main() { 
    C c; 
    return 0; 
} 
+3

* बस एक टिप्पणी: * परिभाषाएं 'शून्य सी :: ए :: foo() {} 'और' शून्य सी :: बी :: foo() {}' शुद्ध वर्चुअल फ़ंक्शंस के लिए परिभाषाएं प्रदान करती हैं 'ए :: foo 'और' बी :: foo' क्रमशः (और आवश्यक नहीं हैं)। – dyp

+0

कहें ** ** ** ** {void c :: foo() {cout << "सी" << endl;} शून्य सी :: ए :: foo() {cout << "ए" << endl ;} शून्य सी :: बी :: foo() {cout << "बी" << endl;}; int मुख्य() { सी सी; c.foo(); ((ए और) सी) .foo(); ((बीएंड) सी) .foo(); वापसी 0; } '** हमेशा आउटपुट 'सी' ** – biv

+0

@dyp बस उत्सुक है कि 'ए :: foo()' की परिभाषा प्रदान करने के लिए वाक्यविन्यास' शून्य सी :: ए :: foo() {} 'का उपयोग करना कानूनी क्यों है, 'ए :: के लिए() {} 'सीधे ओवरराइड करने के बजाय इस तरह के वाक्यविन्यास का उपयोग करने के लिए कोई लाभ? यह मेरे लिए बहुत भ्रमित लग रहा है, अगर 'ए' एक आंतरिक वर्ग है तो क्या होगा? मैंने इस कोड को संकलित किया और आश्चर्यचकित हुआ कि यह कानूनी है। – Dreamer

15

एक समारोह एक आधार नाम और पैरामीटर प्रकार के आधार पर वर्ग का एक आभासी समारोह को ओवरराइड करता है (नीचे देखें) । इसलिए, अपने वर्ग Cदो आभासी कार्यों foo, एक-एक A और B से विरासत में मिली है। लेकिन एक समारोह void C::foo() ओवरराइड दोनों:

[class.virtual]/2

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

जब :

मैं पहले से ही टिप्पणी में कहा गया है, [dcl.meaning]/1 एक (सदस्य) समारोह की घोषणा में एक योग्य-आईडी का उपयोग बैन declarator-आईडी योग्य है, घोषणा वर्ग या नाम स्थान जो करने के लिए क्वालीफायर संदर्भित करता है [...] "

के एक पहले से घोषित सदस्य का उल्लेख करेगा इसलिए किसी भी virtual void X::foo(); illeg है C के अंदर एक घोषणा के रूप में अल।

कोड

class C : public A, public B 
{ 
    virtual void foo(); 
}; 

एक ही रास्ता AFAIK foo ओवरराइड करने के लिए है, और यह A::foo और B::foo दोनों पार कर जाएगी।

#include <iostream> 

struct A 
{ 
    virtual void foo() = 0; 
}; 

struct B 
{ 
    virtual void foo() = 0; 
}; 

struct CA : A 
{ 
    virtual void foo() { std::cout << "A" << std::endl; } 
}; 

struct CB : B 
{ 
    virtual void foo() { std::cout << "B" << std::endl; } 
}; 

struct C : CA, CB {}; 

int main() { 
    C c; 
    //c.foo(); // ambiguous 

    A& a = c; 
    a.foo(); 

    B& b = c; 
    b.foo(); 
} 
संबंधित मुद्दे