व्युत्पन्न वर्ग में एक ही नाम लेकिन विभिन्न हस्ताक्षर के साथ कार्य


92

मेरे पास एक ही नाम के साथ एक फ़ंक्शन है, लेकिन आधार और व्युत्पन्न वर्गों में अलग-अलग हस्ताक्षर के साथ। जब मैं बेस क्लास के फंक्शन को दूसरी क्लास में इस्तेमाल करने की कोशिश कर रहा होता हूँ, जो मुझे व्युत्पन्न होता है, तो मुझे एक त्रुटि मिलती है। निम्नलिखित कोड देखें:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

मुझे gcc संकलक से निम्न त्रुटि प्राप्त होती है:

In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)

अगर मैं int foo(int i){};कक्षा से हटा दूं B, या अगर मैं इसका नाम बदल दूं foo1, तो सब कुछ ठीक है।

इससे क्या परेशानी है?


1
तकनीकी रूप से इस सवाल का एक डुप्लिकेट लेकिन इस एक बेहतर शीर्षक और जवाब है।
Troubadour

जवाबों:


79

व्युत्पन्न वर्ग में कार्य करता है जो आधार वर्ग में कार्यों पर हावी नहीं है, लेकिन जो एक ही नाम होगा छिपाने आधार वर्ग में इसी नाम के अन्य कार्यों।

यह आमतौर पर बुरा अभ्यास माना जाता है कि व्युत्पन्न वर्गों में फ़ंक्शन होते हैं जिनका बास क्लास में फ़ंक्शन के समान नाम होता है जो बेस क्लास फ़ंक्शंस को ओवरराइड करने के लिए अभिप्रेत नहीं होते हैं जैसा कि आप जो देख रहे हैं वह आमतौर पर वांछनीय व्यवहार नहीं है। आमतौर पर विभिन्न कार्यों को अलग-अलग नाम देना बेहतर होता है।

यदि आपको आधार फ़ंक्शन को कॉल करने की आवश्यकता है तो आपको कॉल करके गुंजाइश की आवश्यकता होगी A::foo(s)। ध्यान दें कि यह किसी भी वर्चुअल फ़ंक्शन तंत्र A::foo(string)को उसी समय के लिए अक्षम कर देगा ।


13
यह भी पढ़ें litdb का जवाब: आप बी में 'a: foo' क्लॉज का उपयोग करके बेस फंक्शन को 'अनहाइड' कर सकते हैं
xtofl

सच है, मैं बस एक समाधान देख रहा था जिसे कॉल साइट पर इस्तेमाल किया जा सकता है, जो आधार पदानुक्रम को निर्धारित करता है।
सीबी बेली

2
इस दावे का आधार क्या है और सलाह के बाद: "आम तौर पर यह माना जाता है कि व्युत्पन्न वर्गों में कार्य करने के लिए बुरा व्यवहार होता है, जिसका नाम बास वर्ग के कार्यों के समान होता है जो आधार वर्ग के कार्यों को ओवरराइड करने के लिए नहीं होते हैं। क्या आप देख रहे हैं आमतौर पर वांछनीय व्यवहार नहीं है। यह आमतौर पर विभिन्न कार्यों के अलग-अलग नाम देने के लिए पसंद किया जाता है " । क्या होगा अगर वे शब्दार्थ वही काम कर रहे हैं? C ++ आपको इसके कारण होने वाली समस्या का समाधान प्रदान करता है, जैसा कि जोहान्स के उत्तर द्वारा समझाया गया है।
नवाज

109

ऐसा इसलिए है क्योंकि यदि आपके किसी एक बेस में नाम मिलता है तो नाम लुकअप बंद हो जाता है। यह अन्य आधारों से परे नहीं दिखेगा। B में फ़ंक्शन A में फ़ंक्शन को छाया देता है। आपको B के दायरे में A के फ़ंक्शन को फिर से घोषित करना होगा, ताकि दोनों फ़ंक्शन B और C के भीतर से दिखाई दें:

class A
{
    public:
    void foo(string s){};
};

class B : public A
{
    public:
    int foo(int i){};
    using A::foo;
};

class C : public B
{
    public:
    void bar()
    {
        string s;
        foo(s);
    }
};

संपादित करें: मानक विवरण वास्तविक विवरण देता है (10.2 / 2 से):

निम्नलिखित चरण एक वर्ग दायरे, सी। प्रथम में नाम देखने के परिणाम को परिभाषित करते हैं। सबसे पहले, कक्षा में नाम के लिए प्रत्येक घोषणा और इसके प्रत्येक आधार वर्ग में उप-वस्तुओं पर विचार किया जाता है। एक सब-ऑब्जेक्ट बी में एक सदस्य का नाम एफ, एक उप-ऑब्जेक्ट ए में एक सदस्य का नाम छुपाता है, यदि ए बी का एक आधार वर्ग उप-ऑब्जेक्ट है तो जो भी घोषणाएं छिपी हुई हैं, उन्हें विचार से समाप्त कर दिया जाता है। एक प्रयोग-घोषणा द्वारा पेश किए गए इन घोषणाओं में से प्रत्येक को C के प्रत्येक उप-ऑब्जेक्ट से माना जाता है, जो कि इस प्रकार का है, जो कि घोषणा-घोषणा -9 द्वारा निर्दिष्ट tion से युक्त है) यदि घोषित परिणाम निर्धारित नहीं हैं सभी एक ही प्रकार की उप-वस्तुओं से, या सेट में एक गैर-स्थैतिक सदस्य होता है और इसमें अलग-अलग उप-वस्तुओं के सदस्य शामिल होते हैं, एक अस्पष्टता होती है और कार्यक्रम बीमार होता है। अन्यथा वह सेट लुकअप का परिणाम है।

इसे किसी अन्य स्थान पर कहने के लिए निम्नलिखित है (इसके ठीक ऊपर):

एक आईडी-एक्सप्रेशन [ "फू" जैसा कुछ ] के लिए, नाम लुकअप इस के वर्ग दायरे में शुरू होता है; योग्य-आईडी के लिए [ "A :: foo", A एक नेस्टेड-नेम-स्पेसिफायर है ], नेस्टेड-नेम-स्पेसियर के दायरे में नाम लुकअप शुरू होता है। अभिगम नियंत्रण (3.4, खंड 11) से पहले नाम देखने की जगह लेता है।

([...] मेरे द्वारा डाला गया)। ध्यान दें कि इसका मतलब है कि भले ही बी में आपका फू निजी है, ए में फू अभी भी नहीं मिलेगा (क्योंकि अभिगम नियंत्रण बाद में होता है)।


litb, आपके उत्तर के लिए धन्यवाद। लेकिन जब मैं अपने कोड को संकलित करने का प्रयास करें, मैं मिलता है: करने के लिए उपयोग समायोजित नहीं कर सकते void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in वर्ग बी में एक ही नाम के साथ 'स्थानीय विधि `पूर्णांक बी :: foo (int) की वजह से'। शायद यह इसलिए है क्योंकि मैं जीसीसी के एक पुराने संस्करण का उपयोग करता हूं
इगोर ओक्स

1
हाँ, निश्चित रूप से एक संकलक बग। पुराने संकलक "ए :: फू;" का उपयोग करते थे इसके बजाय "ए :: फू का उपयोग करना;" लेकिन पूर्व C ++ में पदावनत है।
जोहान्स स्काउब - litb
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.