2013-06-04 6 views
9

व्युत्पन्न कक्षा में संरक्षित कन्स्ट्रक्टर को आमंत्रित करने की अनुमति नहीं है, जैसा कि here समझाया गया है।व्युत्पन्न कक्षाओं में संरक्षित स्थैतिक विधि को क्यों कॉल करने की अनुमति है?

स्वीकार किए जाते हैं जवाब है कि protected अनुदान आधार वर्ग A का एक उद्देश्य के सदस्यों के लिए पहुँच ही जब वर्ग A की उस वस्तु वर्ग B की एक subobject है बताते हैं। अब तक सब ठीक है.

लेकिन फिर, स्थिर संरक्षित तरीकों को कॉल करने के लिए इसकी अनुमति क्यों है (कम से कम जीसीसी 4.6.3 में)? विशेष रूप से, यह मेरे लिए कोई मतलब नहीं है कि निम्नलिखित compiles, जबकि टिप्पणी की लाइन नहीं करता है:

class A 
{ 
protected: 
    A() {} 
    static A makeA() { return A(); } 
}; 

class B: public A 
{ 
public: 
    static A makeAFromB() 
    { 
     return makeA(); // compiles 
     // return A(); // does not compile 
    } 
}; 

दार्शनिक, एक निर्माता वर्ग A, कारण है कि की एक वस्तु लौटने एक स्थिर विधि की तरह काफी है मुझे यहाँ व्यवहार में अंतर नहीं मिलता है।

+3

आपको 'वापसी ए :: ए() '' रिटर्न ए() 'में बदलना चाहिए। यह अभी भी संकलित नहीं होगा, लेकिन इस बार यह 'संरक्षित' पहुंच से संबंधित एक कारण के लिए होगा, जिससे सवाल स्पष्ट हो जाएगा। – interjay

+1

आप बिल्कुल सही हैं, संपादित करें। स्पष्टीकरण के लिए – Boris

उत्तर

10

लेकिन फिर, स्थिर संरक्षित तरीकों को कॉल करने के लिए इसकी अनुमति क्यों है (कम से कम जीसीसी 4.6.3 में)?

क्योंकि मानक यही कहता है। बाधाओं कि protected सदस्यों की पहुंच के लिए लागू होते हैं (और है कि इसका जवाब आप लिंक किए गए बहुत अच्छी तरह से बताते हैं) पैराग्राफ में परिभाषित कर रहे हैं सी ++ 11 स्टैंडर्ड, जिसका पहला वाक्य को निर्दिष्ट की 11.4/1:

एक अतिरिक्त पहुँच क्लॉज 11 में पहले वर्णित उन लोगों से परे जांच करें जब गैर-स्थिर डेटा सदस्य या गैर स्थैतिक सदस्य फ़ंक्शन इसके नामकरण वर्ग (11.2) का संरक्षित सदस्य है। [...]

अतिरिक्त एक्सेस चेक स्थिर सदस्यों या स्थैतिक सदस्य कार्यों पर लागू नहीं होता है।

+0

ठीक है धन्यवाद! (और मानक से उद्धरण जो "गैर स्थैतिक" निर्दिष्ट करता है) – Boris

+0

@ बोरीस: खुशी हुई इससे मदद मिली! –

2

आप सही हैं कि केवल संरक्षित बेस ऑब्जेक्ट तक पहुंच प्रदान करने का तरीका आश्चर्यजनक हो सकता है ... लेकिन इसके लिए एक अच्छा कारण है। मान लें कि आपके पास Base से ली गई कुछ कक्षाएं हैं, और उन वर्गों में से एक विधि किसी संदर्भ या सूचक के माध्यम से मनमाने ढंग से Base ऑब्जेक्ट को काम करना चाहता था ... यह हो सकता है कि Base यह अन्य व्युत्पन्न का हिस्सा है चेन, जिसमें Base ऑब्जेक्ट की अन्य व्यवहारिक अपेक्षाएं हैं, जो इसे संरक्षित सदस्य कार्यों के उपयोग के लिए दी गई है। आप प्रभावी ढंग से उस व्युत्पन्न को हटा रहे हैं जो अन्य व्युत्पन्न वर्ग का उद्देश्य है, इसे लक्षित ओएनए व्यवहारों की दुनिया के बाहर कदम उठाने के इरादे से लागू करने से रोकता है .... इस विशिष्ट परिदृश्य को इस अंतर्दृष्टि को लागू करना, सी ++ नियम उस संरक्षित निर्माता का उपयोग करके आपको रोक रहे हैं एक उपरोक्त बनाने के लिए जो कि कुछ व्युत्पन्न वर्ग द्वारा पॉलिसीकृत आविष्कारक होने की उम्मीद थी, जब वास्तव में कोई व्युत्पन्न वस्तु नहीं होती है जिसमें Base ऑब्जेक्ट एम्बेड किया जाएगा।

अलग से, जिस तरह से निर्माताओं के लिए काम करता है protected स्पष्ट उपयोगिता है - यह (है कि निर्माता का प्रयोग करके) वर्ग के निर्माण को रोकता है व्युत्पन्न वर्ग की एक subobject के रूप में छोड़कर, या (जैसे में makeA के रूप में आधार वर्ग के सदस्य कार्यों से अपने उदाहरण) - चाहे वे स्थिर हैं या गैर स्थैतिक सदस्य कार्य अप्रासंगिक हैं ... सभी सदस्य कार्य हमेशा कक्षा में पूर्ण होते हैं।

स्थिर सदस्य कार्यों के लिए private/protected/public के अंतर्ज्ञानी अर्थों को अनदेखा करने में उपयोगिता क्या होगी?आप कह रहे हैं कि आप उन्हें प्रभावी रूप से निजी होने की उम्मीद करते हैं, यदि वह व्यवहार आप चाहते हैं तो बस उन्हें निजी बनाएं/यदि आपको उन्हें सुलभ करने की आवश्यकता है तो उन्हें सुरक्षित रखें। स्पष्ट रूप से संरक्षित पहुंच मेरे पहले पैराग्राफ में औचित्य के अनुसार सीमित है।

+0

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

+0

@ बोरीस: "उम्मीद थी कि आधार के संरक्षित निर्माता को व्युत्पन्न से बुलाया जा सकता है" - हाँ, वहां भी उम्मीद की गई थी! :-) - उम्मीद है कि ऊपर तर्क तर्क "क्यों नहीं" पहलू को समझाने में मदद करता है। 'मेकए' के ​​साथ महत्वपूर्ण अंतर यह है कि कार्यान्वयन अभी भी 'ए 'के नियंत्रण में है ... इसे' ए 'के समावेशन की सीमाओं का निर्धारण करने की अनुमति है, जहां व्युत्पन्न वर्ग का उपयोग करने वाले कन्स्ट्रक्टर का नियंत्रण करने के लिए अनुमति देता है। चीयर्स। –

+0

वास्तव में उपरोक्त तर्क ने आपकी सहायता की, साथ ही साथ आपकी अतिरिक्त टिप्पणी :) मैं अभी भी बहुत नाराज हूं कि मैं विनाशक का आह्वान नहीं कर सकता, लेकिन अच्छी तरह से, कम से कम इसके लिए एक अच्छा कारण है ;-) – Boris

0

स्टेटिक विधियों को इस अर्थ में विरासत में मिला है कि वे बाल वर्ग के तरीकों में उपलब्ध हैं। हम बाल वर्ग के नाम का उपयोग करके या बाल वर्ग के उदाहरण का उपयोग करके, या बाल वर्ग के शरीर में योग्यता के बिना एक स्थिर विधि को कॉल कर सकते हैं।

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