2012-11-23 5 views
118

मैं किसी भी तरह हैरान हूँ कि निम्नलिखित कोड को संकलित करता है और रन (vc2012 & gcc4.7.2)मैं निजी प्रकार पर ऑटो का उपयोग क्यों कर सकता हूं?

class Foo { 
    struct Bar { int i; }; 
public: 
    Bar Baz() { return Bar(); } 
}; 

int main() { 
    Foo f; 
    // Foo::Bar b = f.Baz(); // error 
    auto b = f.Baz();   // ok 
    std::cout << b.i; 
} 

यह है कि इस कोड ठीक संकलित सही है था? और यह सही क्यों है? मैं निजी प्रकार पर auto का उपयोग क्यों कर सकता हूं, जबकि मैं इसका नाम (अपेक्षित के रूप में) का उपयोग नहीं कर सकता?

+10

गौर करें कि 'f.Baz() मैं' घ भी ठीक है के रूप में 'एसटीडी है :: cout << टाइपिड (एफ। बैज़())। नाम() '। कक्षा के बाहर कोड 'बाज़()' द्वारा लौटाए गए प्रकार को "देख" सकता है यदि आप इसे पकड़ सकते हैं, तो आप इसे नाम नहीं दे सकते। –

+2

और यदि आपको लगता है कि यह अजीब है (जो आप शायद करते हैं, जैसा कि आप इसके बारे में पूछ रहे हैं) आप अकेले नहीं हैं;) यह रणनीति [सुरक्षित-बूल मुहावरे] जैसी चीजों के लिए शक्तिशाली है (http: // www .artima.com/cppsource/safebool.html) हालांकि। –

+2

मुझे लगता है कि याद रखने की बात यह है कि 'निजी' एपीआई का वर्णन करने के लिए एक सुविधा के रूप में है कि संकलक लागू करने में मदद कर सकता है। इसका उद्देश्य 'फू' के उपयोगकर्ताओं द्वारा 'बार' प्रकार तक पहुंच को रोकने का इरादा नहीं है, इसलिए यह 'बार' के उदाहरण को वापस कर उस पहुंच की पेशकश से किसी भी तरह से 'Foo' को बाधित नहीं करता है। –

उत्तर

100

auto के नियम अधिकांश भाग के लिए टेम्पलेट प्रकार की कटौती के समान हैं। इसी कारण से आप टेम्पलेट कार्यों के लिए निजी प्रकार की वस्तुओं के लिए पारित कर सकते हैं उदाहरण के पोस्ट काम करता है:

template <typename T> 
void fun(T t) {} 

int main() { 
    Foo f; 
    fun(f.Baz());   // ok 
} 

और क्यों हम टेम्पलेट कार्यों के लिए निजी प्रकार की वस्तुओं पारित कर सकते हैं, आप से पूछना? क्योंकि केवल प्रकार का नाम पहुंच योग्य नहीं है। यह प्रकार अभी भी प्रयोग योग्य है, आप इसे क्लाइंट कोड पर क्यों वापस कर सकते हैं।

+25

और यह देखने के लिए कि * नाम * की गोपनीयता * प्रकार * के साथ कुछ लेना देना नहीं है, सवाल में 'सार्वजनिक: टाइपेडफ बार वापसी_type_from_Baz;' कक्षा में 'Foo'' जोड़ें। वर्ग के निजी वर्ग में परिभाषित होने के बावजूद, इस प्रकार को सार्वजनिक नाम से पहचाना जा सकता है। –

+1

@ स्टीव के बिंदु को दोहराने के लिए: _name_ के लिए एक्सेस विनिर्देशक के पास इसके _type_ से कुछ लेना देना नहीं है, जैसा कि 'निजी: टाइपेडफ बार वापसी_type_from_Baz;' 'Foo'' जोड़कर देखा गया है, जैसा कि [प्रदर्शित] [http://ideone.com/iKv2bQ)। 'typedef''d पहचानकर्ता विनिर्देशकों, सार्वजनिक और निजी तक पहुंचने के लिए अनजान हैं। – damienh

+0

इससे मुझे कोई समझ नहीं आता है। प्रकार का _name_ वास्तविक प्रकार के लिए केवल एक उपनाम है। इससे कोई फर्क नहीं पड़ता कि मैं इसे 'बार' या 'कुछ डीडियोडेड टाइप' कहता हूं? ऐसा नहीं है कि मैं इसे 'कक्षा फू' या किसी भी चीज़ के निजी सदस्यों के लिए उपयोग कर सकता हूं। – einpoklum

98

एक्सेस नियंत्रण नाम पर लागू होता है। इस उदाहरण से तुलना करें मानक से:

class A { 
    class B { }; 
public: 
    typedef B BB; 
}; 

void f() { 
    A::BB x; // OK, typedef name A::BB is public 
    A::B y; // access error, A::B is private 
} 
5

अन्य (अच्छा) उत्तर देने के लिए जोड़ने के लिए, यहां सी ++ 98 से एक उदाहरण दिखाता है कि कि इस मुद्दे को वास्तव में सभी

पर auto साथ क्या करना है नहीं करता है
class Foo { 
    struct Bar { int i; }; 
public: 
    Bar Baz() { return Bar(); } 
    void Qaz(Bar) {} 
}; 

int main() { 
    Foo f; 
    f.Qaz(f.Baz()); // Ok 
    // Foo::Bar x = f.Baz(); 
    // f.Qaz(x); 
    // Error: error: ‘struct Foo::Bar’ is private 
} 

निजी प्रकार का उपयोग प्रतिबंधित नहीं है, यह केवल प्रकार का नामकरण कर रहा था। उस प्रकार का एक अज्ञात अस्थायी बनाना ठीक है, उदाहरण के लिए, C++ के सभी संस्करणों में ठीक है।

8

इस सवाल का जवाब पहले से ही ठंडा और आर मार्टिनो फर्नांडीस द्वारा बहुत अच्छी तरह से दिया गया है।

मैं सिर्फ एक हैरी पॉटर सादृश्य के साथ एक सवाल का जवाब देने के लिए इस अवसर पारित नहीं कर सकता है:।

class Wizard 
{ 
private: 
    class LordVoldemort 
    { 
     void avada_kedavra() 
     { 
      // scary stuff 
     } 
    }; 
public: 
    using HeWhoMustNotBeNamed = LordVoldemort; 
}; 

int main() 
{ 
    Wizard::HeWhoMustNotBeNamed tom; // OK 
    Wizard::LordVoldemort not_allowed; // Not OK 
    return 0; 
} 
+4

एक 'मित्र वर्ग हैरी नहीं है,' वहां लापता है? – Quentin

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