2011-01-22 24 views
9

मैं सी ++ नौसिखिया हूं, और मुझे ओओ भाषाओं जैसे सी/सी #/उद्देश्य-सी के बारे में कई वर्षों का अनुभव है। अब, मैं सी ++ सीख रहा हूँ।सी ++ उप-वर्गीकरण एक्सेस संशोधक?

class World : public State 
    { 
    }; 

यह वर्ग World वर्ग State सार्वजनिक रूप से विरासत में लगता है:

मैं इस सी ++ कोड को देखा। सार्वजनिक उपclassing? समझना मुश्किल है।

इस सुविधा की अवधारणा क्या है? और यह कब उपयोगी या आवश्यक है?

+0

क्या आप 'कक्षा विश्व: निजी राज्य {} 'लिखना चाहते थे? जो आपने वास्तव में लिखा था, वह विरासत सार्वजनिक है। –

+0

क्या आपका मतलब 'वर्ग विश्व: निजी राज्य' था? – detunized

+0

@Steve, @detunized मुझे मेरी बेवकूफ गलती के लिए खेद है। मैंने सवाल संशोधित किया। – Eonil

उत्तर

13

public कीवर्ड की आवश्यकता केवल class कीवर्ड के साथ परिभाषित कक्षाओं के लिए है, डिफ़ॉल्ट एक्सेस संशोधक (सब कुछ के लिए - डेटा सदस्य, सदस्य कार्य, और आधार वर्ग) private है। तो

class World : State {}; 

रूप में ही है:

class World : private State {}; 

और कहा कि शायद नहीं है कि आप क्या चाहते - इसका मतलब है कि आधार वर्ग वर्ग World भीतर ही उपलब्ध है। बाहरी लोग "नहीं जानते" कि विरासत बिल्कुल है।

कीवर्ड struct के साथ परिभाषित वर्गों के लिए, डिफ़ॉल्ट पहुँच संशोधक, public है ताकि आप सकता है लिखने:

struct World : State {}; 

और कुछ पाने कि दोनों दिखता है और विरासत के साथ हर दूसरे भाषा की तरह एक सा व्यवहार करता है। लेकिन struct कीवर्ड, और तथ्य यह है कि यह एक वर्ग को परिभाषित करता है, वास्तव में केवल सी के साथ संगतता के लिए है।आपको कई सी ++ शैली मार्गदर्शिकाएं नहीं मिलेंगी जो डिफ़ॉल्ट सार्वजनिक पहुंच प्राप्त करने के लिए इसका उपयोग करने की अनुशंसा करते हैं - आम तौर पर इसका उपयोग केवल उन वर्गों के लिए किया जाता है जो पीओडी हैं, या शायद केवल उन सदस्यों के लिए, जिनमें कोई सदस्य कार्य नहीं है।

क्यों सी ++ के पास पहली जगह निजी विरासत है: अधिकांश उद्देश्यों के लिए, निजी विरासत संरचना का एक रूप है। सामान्य रचना:

class World { 
    State state; 
    public: 
    void foo() { 
     state.bar(); 
     state.baz(); 
     and so on 
    } 
}; 

है, वर्ग विश्व जानता है कि यह एक राज्य का उपयोग कर लागू किया गया है, और बाहर की दुनिया यह नहीं पता कि विश्व कार्यान्वित किया जाता है।

बनाम

class World : private State { 
    public: 
    void foo() { 
     bar(); 
     baz(); 
     and so on 
    } 
}; 

है, वर्ग विश्व जानता है कि यह द्वारा जा रहा है किसी राज्य को लागू किया है, और बाहर की दुनिया नहीं जानती कि यह कैसे लागू हो जाता है। लेकिन आप चुनिंदा रूप से राज्य के इंटरफ़ेस के हिस्सों का पर्दाफाश कर सकते हैं उदाहरण के लिए using State::bar; को विश्व की परिभाषा के सार्वजनिक भाग में डाल दें। प्रभाव यह है कि आप दुनिया में एक समारोह (या कई अधिभार) को श्रमिक रूप से लिखा होगा, जिनमें से प्रत्येक राज्य पर एक ही कार्य के लिए प्रतिनिधि है।

टाइपिंग से बचने के अलावा, निजी विरासत का एक आम उपयोग तब होता है जब कक्षा State खाली है, यानी कोई डेटा सदस्य नहीं है। फिर यदि यह World का सदस्य है, तो उसे कुछ जगह पर कब्जा कर लेना चाहिए (स्वीकार्य रूप से, ऑब्जेक्ट लेआउट के आधार पर यह ऐसी जगह हो सकती है जो अन्यथा केवल पैडिंग होगी, इसलिए यह World के आकार को जरूरी नहीं है), लेकिन यदि यह बेस क्लास है फिर "खाली बेस क्लास ऑप्टिमाइज़ेशन" नामक एक चीज़ में शामिल होता है, और यह शून्य आकार का हो सकता है। यदि आप ऑब्जेक्ट्स के लॉट बना रहे हैं, तो इससे कोई फर्क नहीं पड़ता। निजी विरासत अनुकूलन को सक्षम बनाता है, लेकिन बाहरी दुनिया "एक-एक" रिश्ते का अनुमान नहीं लगाएगी, क्योंकि यह विरासत को नहीं देखती है।

यह एक बहुत अच्छा अंतर है - यदि संदेह में स्पष्ट संरचना का उपयोग करें। टाइपिंग को बचाने के लिए विरासत का परिचय देना बहुत अच्छा है जब तक कि इसका कुछ अप्रत्याशित परिणाम न हो।

+0

धन्यवाद। स्वीकृत क्योंकि अंतिम पैराग्राफ :) – Eonil

3

आपको क्या लगता है कि यह निजी है? यह वहां सार्वजनिक रूप से कहता है, जिसका अर्थ है कि यह सार्वजनिक रूप से उप-वर्गीकरण है।

एक तरफ, निजी और संरक्षित विरासत सार्वजनिक विरासत के समान ही है, सिवाय इसके कि सभी सदस्य चर हैं, कम से कम निजी या संरक्षित पहुंच के साथ कार्य विरासत में हैं। उदाहरण के लिए, यदि State में सार्वजनिक सदस्य फ़ंक्शन 'foo()' था, तो यह 'दुनिया' में निजी होगा।

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

संरचना के लिए निजी विरासत का उपयोग करने का एक लाभ खाली बेस क्लास ऑप्टिमाइज़ेशन (ईबीसीओ) से आता है। सामान्य संरचना का उपयोग करते हुए, एक खाली वर्ग का सदस्य ऑब्जेक्ट होने पर कम से कम 1 बाइट का उपयोग किया जाएगा क्योंकि सभी चरों में एक अद्वितीय पता होना चाहिए। यदि आप उस ऑब्जेक्ट को निजी रूप से प्राप्त करते हैं जिसे आप बनाते हैं तो वह लागू नहीं होता है और आपको स्मृति हानि नहीं होगी।

उदा।

class Empty { }; 

class Foo 
{ 
    int foo; 
    Empty e; 
}; 

class Bar : private Empty 
{ 
    int foo; 
}; 

यहाँ, sizeof(Foo) संभवत: 5 होगा, लेकिन sizeof(Bar) खाली आधार वर्ग की वजह से 4 हो जाएगा।

+0

"सार्वजनिक विरासत के समान, इसके अलावा ..."। अंतर सिर्फ इतना ही है। इसके अलावा, बाहरी लोग उदाहरण के लिए 'राज्य *' को 'राज्य *' में static_cast नहीं कर सकते हैं। –

+0

"आकार (फू) शायद 5 होगा" - या इससे भी बदतर 8, यदि आपके कार्यान्वयन पर 'int' 4-गठबंधन है। –

+0

@ स्टेव जेसप: सच। –

4

मामले में

class World: private State 
{ 
}; 

निजी वंशानुक्रम का मतलब है कि State के सभी public और protected सदस्यों World द्वारा विरासत में मिला दिया जाएगा और private बन जाएगा। यह StateWorld के अंदर सील करता है। World से विरासत में कोई भी कक्षा State की किसी भी सुविधा तक पहुंच पाएगी।

0

पूर्वजों के नाम से पहले सार्वजनिक/संरक्षित/निजी कीवर्ड पूर्वजों के सदस्यों की वांछित दृश्यता को इंगित करता है। निजी विरासत के साथ, वंश को केवल पूर्वजों से कार्यान्वयन प्राप्त होता है, लेकिन इंटरफ़ेस नहीं।

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

class B : private A { 
public: 
    void bar(); 
}; 

void B::bar() 
{ 
    foo(); // can access foo() 
} 

B b; 
b.foo(); // forbidden 
b.bar(); // allowed 

सामान्य तौर पर, आप सार्वजनिक भाग का उपयोग करना चाहिए क्योंकि विरासत कार्यान्वयन केवल पुनः उपयोग के लिए नहीं किया जाना चाहिए (जो क्या निजी वंशानुक्रम करता है)।

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