अपने प्रश्न के शब्दों को देखते हुए (आपने "छिपाने" शब्द का उपयोग किया है), आप पहले से ही जानते हैं कि यहां क्या चल रहा है। घटना को "नाम छिपाना" कहा जाता है। किसी कारण से, हर बार जब कोई व्यक्ति सवाल करता है कि नाम छिपाना क्यों होता है, तो जवाब देने वाले लोग या तो कहते हैं कि यह "नाम छिपाना" कहलाता है और समझाता है कि यह कैसे काम करता है (जो आप शायद पहले से जानते हैं), या इसे कैसे ओवरराइड करें (जो आप जानते हैं के बारे में कभी नहीं पूछा), लेकिन किसी को भी "क्यों" प्रश्न के वास्तविक पते की परवाह नहीं है।
निर्णय, नाम छुपाने के पीछे तर्क, अर्थात यह वास्तव में C ++ में क्यों बनाया गया था, कुछ प्रतिपक्षी, अप्रत्याशित और संभावित खतरनाक व्यवहार से बचने के लिए है जो कि हो सकता है यदि ओवरलोड कार्यों के विरासत में मिला सेट को वर्तमान सेट के साथ मिश्रण करने की अनुमति दी गई थी। दिए गए वर्ग में अधिभार। आप शायद जानते हैं कि C ++ में अधिभार संकल्प उम्मीदवारों के सेट से सबसे अच्छा कार्य चुनकर काम करता है। यह मापदंडों के प्रकारों के प्रकारों के मिलान द्वारा किया जाता है। मिलान नियम कई बार जटिल हो सकते हैं, और अक्सर उन परिणामों को जन्म देते हैं जिन्हें एक अप्रस्तुत उपयोगकर्ता द्वारा अतार्किक माना जा सकता है। पहले से मौजूद लोगों के एक सेट में नए कार्यों को जोड़ने के परिणामस्वरूप ओवरलोड रिज़ॉल्यूशन परिणामों में भारी बदलाव हो सकता है।
उदाहरण के लिए, मान लें कि आधार वर्ग B
का सदस्य कार्य हैfoo
जो प्रकार का पैरामीटर लेता है void *
, और सभी कॉल को foo(NULL)
हल किया जाता है B::foo(void *)
। मान लीजिए कि कोई नाम नहीं छिपा है और यह B::foo(void *)
कई अलग-अलग वर्गों में दिखाई दे रहा है B
। हालाँकि, मान लें कि कुछ [अप्रत्यक्ष, दूरस्थ] D
वर्ग के वंशज B
एक फ़ंक्शन foo(int)
परिभाषित है। अब, बिना नाम छिपाने D
के दोनों foo(void *)
और foo(int)
दिखाई देते हैं और अधिभार संकल्प में भाग लेते हैं। यदि किस foo(NULL)
प्रकार की वस्तु के माध्यम से कॉल किया जाता है, तो किस फ़ंक्शन को हल करना होगा D
? वे करने का संकल्प लेंगे D::foo(int)
, क्योंकि int
अभिन्न शून्य (यानी) के लिए एक बेहतर मैच हैNULL
) किसी भी सूचक प्रकार से। इसलिए, पूरे पदानुक्रम में foo(NULL)
एक फ़ंक्शन को हल करने के लिए कॉल किया जाता है , जबकि D
(और अंडर में) वे अचानक दूसरे को हल करते हैं।
एक और उदाहरण C ++ के डिजाइन और विकास में दिया गया है , पृष्ठ 77:
class Base {
int x;
public:
virtual void copy(Base* p) { x = p-> x; }
};
class Derived{
int xx;
public:
virtual void copy(Derived* p) { xx = p->xx; Base::copy(p); }
};
void f(Base a, Derived b)
{
a.copy(&b); // ok: copy Base part of b
b.copy(&a); // error: copy(Base*) is hidden by copy(Derived*)
}
इस नियम के बिना, बी की स्थिति आंशिक रूप से अपडेट की जाएगी, जिससे स्लाइसिंग हो सकती है।
जब भाषा डिजाइन की गई थी तब यह व्यवहार अवांछनीय माना गया था। एक बेहतर दृष्टिकोण के रूप में, "नाम छिपाना" विनिर्देश का पालन करने का निर्णय लिया गया, जिसका अर्थ है कि प्रत्येक वर्ग "क्लीन शीट" के साथ शुरू होता है, प्रत्येक विधि के नाम के संबंध में यह घोषित करता है। इस व्यवहार को ओवरराइड करने के लिए, उपयोगकर्ता से एक स्पष्ट कार्रवाई की आवश्यकता होती है: मूल रूप से विरासत में मिली विधि (एस) (वर्तमान में पदावनत) का पुनर्वितरण, अब उपयोग-घोषणा का एक स्पष्ट उपयोग।
जैसा कि आपने अपने मूल पोस्ट में सही ढंग से देखा है (मैं "पॉलीमॉर्फिक टिप्पणी नहीं" का उल्लेख कर रहा हूं), इस व्यवहार को कक्षाओं के बीच आईएस-ए संबंधों के उल्लंघन के रूप में देखा जा सकता है। यह सच है, लेकिन जाहिरा तौर पर वापस तो यह तय किया गया था कि अंत में नाम छिपाना कम बुराई साबित होगा।