2012-09-04 21 views
21

में आधार वर्ग के संरक्षित सदस्य तक नहीं पहुंच सकता। अपराधी b.a = &b; असाइनमेंट है: जीसीसी और क्लैंग दोनों शिकायत करते हैं कि A() संरक्षित है, जो कोई समस्या नहीं होनी चाहिए क्योंकि बी विरासत में आता है। मानक के किस अंधेरे कोने में मैं आ गया हूं?मैं निम्नलिखित कोड है व्युत्पन्न वर्ग

+3

आप केवल 'इस' आधार (उसी उदाहरण) के 'संरक्षित' सदस्यों तक पहुंच सकते हैं। 'यह' और' बी' एक ही उदाहरण नहीं हैं। – jrok

+2

@ माइकसेमोर नोप। (लेकिन मैं मानता हूं कि मैंने हाल ही में एक ही चीज़ को सोचा था) –

+0

मुझे यकीन है कि यह कई बार पहले पूछा गया है, लेकिन सटीक डुप्लिकेट का पता लगाना मुश्किल है। – dasblinkenlight

उत्तर

21

protected का अर्थ है कि व्युत्पन्न प्रकार अपने स्वयं के आधार किसी भी यादृच्छिक वस्तु * की और नहीं की कि सदस्य के लिए उपयोग होगा है। आपके मामले में, आप संशोधित करना b के सदस्य जो आपके नियंत्रण से बाहर है की कोशिश कर रहा केयर (यानी आप this->a सेट कर सकते हैं, लेकिन नहीं b.a)

वहाँ अगर आप चाहते हैं कि यह काम करने के लिए प्राप्त करने के लिए एक हैक है, लेकिन एक बेहतर समाधान कोड को दोबारा करने के लिए होगा और हैक पर निर्भर नहीं होगा। उदाहरण के लिए, A में एक निर्माता है कि तर्क के रूप में एक A* लेता है प्रदान कर सकता है (इस निर्माता सार्वजनिक होना चाहिए) और फिर B के प्रारंभकर्ता सूची में प्रारंभ:

A::A(A* p) : a(p) {} 
B::B() : b(&b) {} 

*protected अनुदान आप अपने स्वयं के प्रकार के किसी भी उदाहरण में आधार सदस्य तक पहुंच सकते हैं या अपने स्वयं के प्रकार से व्युत्पन्न होते हैं।

+1

+1: मैं हमेशा यह कहता हूं कि "प्रति-वर्ग आधार पर अभिगम नियंत्रण कार्य नहीं करता है, न कि एक प्रति-वस्तु आधार ", लेकिन ऐसा लगता है कि 'संरक्षित' इस नियम का अपवाद है? –

+1

@ जेसे गुड: वास्तव में नहीं, यह अभी भी प्रति-वर्ग है। मैं शायद जवाब में बहुत अस्पष्ट था। आपके पास 'बी' प्रकार के किसी भी ऑब्जेक्ट में सदस्य की पहुंच है या 'बी' से व्युत्पन्न है, केवल 'ए' की वस्तुओं में नहीं है या' ए 'से प्राप्त नहीं है (जो 'बी' नहीं हैं) –

+0

नोट करें कि आप भी चाल कर सकते हैं एक reinterpret_cast का उपयोग कर संकलक। बदसूरत, और खतरनाक हो सकता है, लेकिन ... – Macmade

0

मेरे द्वारा परीक्षण किए गए सभी कंपाइलर्स ने कई चीजों के बारे में शिकायत की है, और विशेष रूप से संरक्षित कन्स्ट्रक्टर एक समस्या होगी, भले ही असाइनमेंट स्टेटमेंट हटा दिया गया हो।

आपको किसी प्रकार के किसी भी उदाहरण के protected सदस्यों तक पहुंच नहीं है। यह मुद्दा 11.4p1 के उदाहरणों में स्पष्ट किया गया है।

class B { 
protected: 
    int i; 
    static int j; 
}; 

class D1 : public B { 
}; 

class D2 : public B { 
    void mem(B*, D1*); 
}; 

void D2::mem(B* pb, D1* p1) { 
    pb->i = 1; // ill-formed 
    p1->i = 2; // ill-formed 
    // ... 
} 
2

वास्तव में यहां दो अलग-अलग समस्याएं हैं।

पहला यह है कि रेखा केवल एक असाइनमेंट नहीं करती है, लेकिन बेस क्लास (जो ठीक काम करती है) और सदस्य b प्रारंभ करने का प्रयास करती है। b सदस्य बनाने के लिए इसे बनाने की आवश्यकता है, और सदस्य के रूप में इसे public किसी कन्स्ट्रक्टर तक पहुंच की आवश्यकता है, जो उसके पास नहीं है।

फिर असाइनमेंट भी b के गैर-सार्वजनिक सदस्य तक पहुंचने में असमर्थ है क्योंकि यह B टाइप नहीं है बल्कि इसके बजाय A टाइप करें।

याद रखें protected मतलब है कि आप एक B वस्तु (या बच्चे) के माध्यम से Aके कुछ हिस्सों का उपयोग कर सकते केवल

इस मामले में हमें अपनी वास्तविक समस्या बताएं और हम इसे हल करने में मदद करने के लिए प्रयास कर सकते हैं। एक ही प्रकार से विरासत और रचना एक डिजाइन गंध है।

+0

"एक ही प्रकार से विरासत और रचना एक डिजाइन गंध है।" क्यों यह है? क्या आप विस्तार से समझा सकते हैं? मैं हाल ही में एक डिजाइन और व्युत्पन्न कक्षा में हूं, आधार (रचना) के कई उदाहरण हैं। ऐसे परिदृश्य में, मुझे उन मूल उदाहरणों के संरक्षित सदस्यों तक पहुंचने की आवश्यकता है जो मेरे व्युत्पन्न वर्ग कार्यों के भीतर से हैं - वहां संकलन त्रुटियां हैं। यदि सुरक्षित पहुंच विनिर्देशक प्रति वर्ग (प्रति उदाहरण के बजाए) हैं, तो इसकी अनुमति दी जानी चाहिए - क्यों नहीं? – h9uest

+0

हाय मार्क। मैंने नीचे एक विशिष्ट प्रश्न तैयार किया है, क्या आप कृपया मुझे प्रबुद्ध करने के लिए एक पल लेंगे?(मानक ने "व्युत्पन्न वस्तु के माध्यम से आधार तक पहुंचने" के समान कुछ भी नहीं कहा; पृष्ठ 237 पर धारा 11 स्पष्ट रूप से बताता है कि उस वर्ग से प्राप्त कक्षाओं द्वारा संरक्षित नाम का उपयोग किया जा सकता है। दूसरे शब्दों में, यह कक्षा के आधार पर और उदाहरण पर काम करता है तस्वीर में नहीं आता है।) चीयर्स। http://stackoverflow.com/questions/34588930/c- संरक्षित-fail-to-access-bases- संरक्षित-member-from-within-derived-class/34589641?noredirect=1#comment56950922_34589641 – h9uest

0

यह सी ++ भाषा की एक बड़ी सीमा की तरह लगता है।कैसे आप इस तरह की समस्या का समाधान होगा:

class Node 
{ 
public: 
void Save(); 
protected: 
virtual void SaveState(int type) = 0; 
}; 

class BinaryNode : public Node 
{ 
protected: 
Node *left; 
Node *right; 

virtual void SaveState(int type) override 
{ 
    left->SaveState(type); 
    right->SaveState(type); 
} 
}; 

इस उदाहरण मैं विधि SaveState दिखाई बाहर Node पदानुक्रम बनाने के लिए नहीं करना चाहते हैं। केवल विधि Savepublic होना चाहिए।

+0

यदि कोई "नोड" छुपाता है उपयोगकर्ता से बचत प्रक्रिया का विवरण तब आपको "बाइनरी नोड" में इसका प्रभाव नहीं देना चाहिए, क्योंकि आपको सटीक प्रकार का "नोड *" नहीं पता है और आप इसके आंतरिक कार्यान्वयन के बारे में अनुमान नहीं लगा सकते हैं। अन्य मामले में आपको बाहर से प्रभावित करने के लिए "सहेजें" के लिए कुछ तर्क जोड़ने की आवश्यकता है या अपना उदाहरण अधिक स्पष्ट बनाएं –

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