2013-03-24 8 views
8

कहते हैं कि हम इस राशि:व्युत्पन्न सार कक्षा में शुद्ध आभासी तरीकों

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

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

संकलक थ्रो कोई त्रुटि है, मैं अपने अनुमान क्योंकि बी भी एक अमूर्त वर्ग है और इस तरह के रूप में यह एक से foo लागू करने के लिए नहीं है लेकिन इस तरह के निर्माण का क्या अर्थ है?

1) 0 से foo बी से foo ए से छिपाता है?

2) प्रथम श्रेणी जो बी से विरासत और एक अमूर्त वर्ग नहीं है, यह दो कार्यान्वयन की तरह प्रदान करने के लिए है:

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

संकलक केवल शिकायत करता है, तो B::foo() के कार्यान्वयन याद आ रही है, लेकिन यह अनुपलब्ध A::foo() के बारे में शिकायत नहीं करता है।

सब कुछ: क्या यह शुद्ध आभासी तरीकों को छिपाने का एक तरीका है?

+1

आप इसे वास्तव में किस प्रकार छिपाया? – Alon

+0

यदि मैं सी में ए :: foo() के लिए कार्यान्वयन प्रदान नहीं करता हूं, तो मैं सी के किसी ऑब्जेक्ट को भी चालू कर सकता हूं। इसलिए सी को हमेशा तत्काल किया जा सकता है, भले ही ए :: foo() गुम हो। तो मैंने सोचा कि सी में किसी भी तरह ए :: foo() की आवश्यकता नहीं है, इसलिए "छुपा"। – Juergen

+1

क्योंकि बी विरासत में आता है .. – Alon

उत्तर

8

जब आप पहली बार घोषणा:

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

आप विधि की घोषणा कर रहे हैं foo, सार्वजनिक आभासी और शुद्ध। जब किसी वर्ग में कम से कम एक शुद्ध विधि होती है तो इसे अमूर्त कहा जाता है। इसका क्या मतलब है? इसका मतलब है कि वर्ग को तत्काल नहीं किया जा सकता क्योंकि इसे शुद्ध विधियों के कार्यान्वयन की आवश्यकता है।

आप स्पष्ट रूप से एक अमूर्त वर्ग से उत्तराधिकारी हो सकते हैं (मैं कहूंगा कि आपको ऐसा करने के लिए मजबूर होना पड़ता है, अन्यथा एक अमूर्त वर्ग की आवश्यकता होगी जिसका उपयोग आप नहीं कर रहे हैं, इसके अलावा इंटरफ़ेस प्रदान करने के अलावा?) और आप एक अमूर्त वर्ग से भी उत्तराधिकारी हो सकते हैं और माता-पिता वर्ग के कुछ या सभी शुद्ध तरीकों को लागू नहीं कर सकते हैं;

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

बी में आप आसानी से virtual void foo() = 0; घोषणा को छोड़ सकता है क्योंकि परिभाषा पहले से ही आधार वर्ग से विरासत में मिली है: इस मामले में बच्चे के वर्ग के रूप में अच्छी तरह से जो अपने वर्ग बी के मामले है सार है,। इस मामले वर्ग बी में एक अमूर्त वर्ग है और इसलिए, instantiated नहीं किया जा सकता है सिर्फ ए

की तरह अधिक सीधे आपके सवालों के जवाब के लिए:

एक से बी छिपाने foo से foo करता है?

नहीं, ऐसा नहीं है। वे दोनों एक शुद्ध विधि घोषित कर रहे हैं (जो वास्तव में एक ही विधि है), इसलिए वास्तव में छिपाने के लिए कुछ भी नहीं है।

बी से विरासत वाली पहली कक्षा और एक अमूर्त वर्ग नहीं है, क्या इसे प्रदान किए गए दो कार्यान्वयन प्रदान करना है?

नहीं, बिल्कुल नहीं। जैसा कि ऊपर कहा, वे एक ही तरीका है, इसलिए यदि क्लास सी foo के लिए क्रियान्वयन की यह सिर्फ foo को लागू करना चाहिए प्रदान करने के लिए है:

class C: public B 
{ 
    public: 
    virtual void foo() {}; 
}; 
+0

कक्षा सी में वास्तव में 'वर्चुअल' की आवश्यकता है क्या यह सिर्फ 'शून्य foo() {}; 'नहीं हो सकता है? –

+0

सी ++ मानक के अनुसार, नहीं, इसकी आवश्यकता नहीं है। हालांकि मुझे यह और अधिक पठनीय लगता है। – Shoe

7

0) संकलक कोई त्रुटि फेंकता है ...

यह है जब आप A या B जो वे सार कर रहे हैं से एक वस्तु का दृष्टांत करने की कोशिश में एक त्रुटि फेंक देते हैं। जब आप विरासत में नहीं होते और उन्हें घोषित नहीं करते हैं।

 

1) एक से बी छिपाने foo से foo करता है?

नहीं। यह A::foo ओवरराइड करता है इसे छुपाता नहीं है।

 

2) प्रथम श्रेणी जो बी से विरासत और एक अमूर्त वर्ग नहीं है, यह दो कार्यान्वयन प्रदान करने के लिए है ...

नहीं। बस foo ओवरराइड और इसके लिए एक कार्यान्वयन करें।

error: cannot define member function ‘A::foo’ within ‘C’ 
error: cannot define member function 'B::foo' within 'C' 

आप उदाहरण में, दोनों वर्ग A और B foo के बाद से अमूर्त वर्ग हैं:

 

class C : public B 
{ 
public: 
    virtual void foo() 
    { 
     std::cout << "ABCD" << std::endl; 
    } 
}; 


int main() 
{ 
    C c; 
    A *a = &c; 
    a->foo(); // Prints ABCD string and proofs B::foo doesn't hide A::foo 
} 
+0

यदि बी :: foo() ए :: foo() को छुपा नहींता है तो सी को इसे लागू करने की अनुमति क्यों नहीं है? – Juergen

+1

यदि आप 'सी' से ऑब्जेक्ट प्राप्त करना चाहते हैं तो इसे' foo' – deepmax

+2

लागू करना होगा, 'बी :: foo' 'A :: foo' जैसा नहीं है, और इसे छुपाता है (साथ ही इसे ओवरराइड करता है) । –

1

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

Question 1:Does foo from B hide foo from A?

B में foo और A बिल्कुल एक ही नाम, एक ही हस्ताक्षर और foo है, आधार वर्ग में आभासी है, इसलिए यह छुपा नहीं है, यह अधिभावी है के बाद से।एफवाईआई: एक व्युत्पन्न वर्ग का कार्य overrides एक बेस क्लास फ़ंक्शन यदि हस्ताक्षर समान है और इसे बेस क्लास में वर्चुअल घोषित किया गया है। यदि आप को पॉइंटर या बेस क्लास के संदर्भ के माध्यम से कॉल करते हैं, तो व्युत्पन्न कक्षा में फ़ंक्शन को कॉल किया जाता है। यह बेस क्लास में "ओवरराइड" करता है। Hiding केवल तभी खेलता है जब आप पॉइंटर या संदर्भ या व्युत्पन्न कक्षा के किसी ऑब्जेक्ट के साथ सीधे गैर-वर्चुअल फ़ंक्शन को कॉल करते हैं। एक व्युत्पन्न वर्ग 'फ़ंक्शन एक ही नाम के साथ सभी बेस क्लास फ़ंक्शंस छुपाता है।

Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations

नहीं, आप निम्न कर सकते हैं:

class C: public B 
    { 
    public: 
     virtual void foo() 
     { 
     cout << "foo defined in c" <<endl; 
     } 
}; 
+0

मैं पुष्टि करता हूं कि जीसीसी त्रुटि संदेशों को फेंक देता है, जबकि दृश्य सी ++ कंपाइलर नहीं करता है। – Juergen

+1

@Juergen इसकी पुष्टि करने के लिए धन्यवाद। – taocp

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