2009-09-27 10 views
7

मैं C++ एक समस्या का सामना करना पड़ रहा हूँ:सी ++ ओवरराइड/अधिभार समस्या

#include <iostream> 

class A 
{ 
protected: 
    void some_func(const unsigned int& param1) 
    { 
    std::cout << "A::some_func(" << param1 << ")" << std::endl; 
    } 
public: 
    virtual ~A() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

int main(int, char**) 
{ 
    A* t = new B(); 
    t->some_func(21, "some char*"); 
    return 0; 
} 

मैं जी ++ 4.0.1 और संकलन त्रुटि उपयोग कर रहा हूँ:

$ g++ -W -Wall -Werror test.cc 
test.cc: In member function ‘virtual void B::some_func(const unsigned int&, const char*)’: 
test.cc:24: error: no matching function for call to ‘B::some_func(const unsigned int&)’ 
test.cc:22: note: candidates are: virtual void B::some_func(const unsigned int&, const char*) 

क्यों मुझे लगता है कि निर्दिष्ट करना होगा है कक्षा बी में some_func (param1) की कॉल A :: some_func (param1) है? क्या यह विशेष मामलों को रोकने के लिए g ++ बग या यादृच्छिक संदेश है जो मुझे नहीं दिख रहा है?

+0

कि अजीब बात है। एक संरक्षित बेस क्लास फ़ंक्शन उप-वर्ग, वर्चुअल, अधिभारित या नहीं के लिए दृश्यमान होना चाहिए। –

उत्तर

11

समस्या यह है कि व्युत्पन्न वर्ग में आप आधार वर्ग में संरक्षित विधि छुपा रहे है। आप चीजों की एक जोड़ी कर सकते हैं, या तो आप पूरी तरह से व्युत्पन्न वस्तु में संरक्षित विधि अर्हता वरना आप एक निर्देश का उपयोग कर के साथ दायरे में है कि विधि लाने:

class B : public A 
{ 
protected: 
    using A::some_func; // bring A::some_func overloads into B 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    A::some_func(param1); // or fully qualify the call 
    } 
}; 
+0

मैं इसे क्यों छुपा रहा हूं? मैं सिर्फ दूसरे को ओवरराइड कर रहा हूं। आम तौर पर, जी ++ को बी के vtable में अधिभारित init के हस्ताक्षर रखना है, लेकिन यह मामला नहीं है। यह हर विधि के हस्ताक्षर क्यों नहीं रखता है? यह अधिभारित क्यों खो देता है (मैं बस उनमें से एक को फिर से परिभाषित कर रहा हूं)? – fedj

+1

जब आप व्युत्पन्न कक्षा में किसी नाम के साथ कोई विधि परिभाषित करते हैं, तो यह पदानुक्रम में उपरोक्त नाम के साथ अन्य सभी विधियों को छुपाएगा। जब संकलक को पता चलता है कि आप स्थिर प्रकार बी के संदर्भ के माध्यम से 'some_func' को कॉल कर रहे हैं तो यह बी के भीतर' some_func 'की सभी घटनाओं के खिलाफ मिलान करने का प्रयास करेगा और बेस क्लास में संभावित मिलान खोजने के लिए पदानुक्रम को आगे बढ़ाने की कोशिश नहीं करेगा। –

+0

क्या यह बड़ा vtable आकार से बचने के लिए एक डिफ़ॉल्ट जी ++ व्यवहार है या यह सी ++ परिभाषा है और प्रत्येक कंपाइलर एक ही त्रुटि करेगा? सामान्य रूप से, यदि यह कक्षा ए में एक अधिभार नहीं था (एक अन्य विधि नाम कहें), हस्ताक्षर वर्ग बी vtable में कॉपी किया गया होगा। – fedj