बीच क्या अंतर है
public
,private
औरprotected
में भाग सी ++?
एसओ पर पाए गए सभी प्रश्न विशिष्ट मामलों से संबंधित हैं।
बीच क्या अंतर है
public
,private
औरprotected
में भाग सी ++?
एसओ पर पाए गए सभी प्रश्न विशिष्ट मामलों से संबंधित हैं।
जवाबों:
उस प्रश्न का उत्तर देने के लिए, मैं सबसे पहले अपने स्वयं के शब्दों में सदस्य के अभिगमकर्ताओं का वर्णन करना चाहूंगा। यदि आप यह पहले से ही जानते हैं, तो शीर्षक "अगला:" पर जाएं।
वहाँ तीन accessors कि मैं के बारे में पता कर रहा हूँ कर रहे हैं: public
, protected
औरprivate
।
करते हैं:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
Base
वह भी सब जानते Base
हैं publicMember
।Base
इसमें शामिल हैं protectedMember
।Base
को पता नहीं है privateMember
।द्वारा "के बारे में पता है", मेरा मतलब है "के अस्तित्व को स्वीकार करते हैं, और इस प्रकार उपयोग करने में सक्षम होते हैं"।
ऐसा ही सार्वजनिक, निजी और संरक्षित विरासत के साथ होता है। आइए एक वर्ग Base
और एक वर्ग पर विचार करें Child
जो विरासत में मिला है Base
।
public
, तो वह सब कुछ जिसके बारे में पता है Base
और Child
यह भी कि Child
विरासत में मिला है Base
।protected
, केवल Child
, और उसके बच्चे, जानते हैं कि वे विरासत में हैंBase
।private
, तो विरासत के अलावा किसी और Child
को पता नहीं है।SomeBase
तरह से विरासत में मिला है, एक गुमनाम सदस्य के प्रकार की रचना करने के लिए एक हार्डकोड तरीका है SomeBase
। यह, किसी भी अन्य सदस्य की तरह, एक एक्सेस स्पेसियर है, जो बाहरी एक्सेस पर समान नियंत्रण रखता है।
class A
{
public:
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
// x is public
// y is protected
// z is not accessible from B
};
class C : protected A
{
// x is protected
// y is protected
// z is not accessible from C
};
class D : private A // 'private' is default for classes
{
// x is private
// y is private
// z is not accessible from D
};
महत्वपूर्ण नोट: कक्षा बी, सी और डी सभी में चर x, y और z होते हैं। यह सिर्फ पहुंच का सवाल है।
संरक्षित और निजी विरासत के उपयोग के बारे में आप यहां पढ़ सकते हैं ।
विरासत की दृश्यता को सीमित करने से कोड यह देखने में सक्षम नहीं होगा कि कुछ वर्ग किसी अन्य वर्ग को विरासत में मिला है: व्युत्पन्न से व्युत्पन्न आधार तक के रूपांतरण काम नहीं करेंगे, और static_cast
आधार से व्युत्पन्न तक भी काम नहीं करेगा।
केवल एक वर्ग के सदस्य / मित्र निजी विरासत देख सकते हैं, और केवल सदस्य / मित्र और व्युत्पन्न वर्ग संरक्षित विरासत देख सकते हैं।
सार्वजनिक विरासत
आईएस-ए विरासत है। एक बटन एक खिड़की है, और कहीं भी एक खिड़की की जरूरत है, एक बटन भी पारित किया जा सकता है।
class button : public window { };
संरक्षित विरासत
रक्षित कार्यान्वित-के-शब्द। शायद ही कभी उपयोगी हो। में प्रयुक्त boost::compressed_pair
खाली वर्गों से और स्मृति को बचाने खाली आधार वर्ग अनुकूलन का उपयोग कर (उदाहरण के नीचे बिंदु पर जा रहा रखने के लिए टेम्पलेट का उपयोग नहीं करता है) प्राप्त करने के लिए:
struct empty_pair_impl : protected empty_class_1
{ non_empty_class_2 second; };
struct pair : private empty_pair_impl {
non_empty_class_2 &second() {
return this->second;
}
empty_class_1 &first() {
return *this; // notice we return *this!
}
};
निजी विरासत
कार्यान्वित-इन-शर्तों-की। बेस क्लास का उपयोग केवल व्युत्पन्न वर्ग को लागू करने के लिए है। लक्षणों के साथ उपयोगी है और यदि आकार मायने रखता है (खाली लक्षण जो केवल फ़ंक्शन होते हैं, खाली आधार वर्ग अनुकूलन का उपयोग करेंगे)। अक्सर रोकथाम बेहतर समाधान है, हालांकि। स्ट्रिंग्स के लिए आकार महत्वपूर्ण है, इसलिए यह अक्सर देखा जाने वाला उपयोग है
template<typename StorageModel>
struct string : private StorageModel {
public:
void realloc() {
// uses inherited function
StorageModel::realloc();
}
};
जनता का सदस्य
कुल
class pair {
public:
First first;
Second second;
};
पहुंचकर्ता
class window {
public:
int getWidth() const;
};
संरक्षित सदस्य
व्युत्पन्न वर्गों के लिए बढ़ाया पहुंच प्रदान करना
class stack {
protected:
vector<element> c;
};
class window {
protected:
void registerClass(window_descriptor w);
};
निजी सदस्य
कार्यान्वयन विवरण रखें
class window {
private:
int width;
};
ध्यान दें कि सी-स्टाइल कास्ट जानबूझकर एक सुरक्षित या निजी बेस क्लास के लिए एक परिभाषित और सुरक्षित तरीके से एक व्युत्पन्न वर्ग को कास्टिंग करने की अनुमति देता है और दूसरी दिशा में भी डाली जाती है। इसे हर कीमत पर टाला जाना चाहिए, क्योंकि यह कार्यान्वयन विवरण पर कोड को निर्भर बना सकता है - लेकिन यदि आवश्यक हो, तो आप इस तकनीक का उपयोग कर सकते हैं।
दृश्यता विरासत मॉडल को निर्दिष्ट करने के लिए इन तीन कीवर्ड का उपयोग पूरी तरह से अलग संदर्भ में भी किया जाता है ।
यह तालिका घटक घोषणा और वंशानुक्रम मॉडल के सभी संभावित संयोजनों को इकट्ठा करती है जिसके परिणामस्वरूप घटकों तक पहुंच होती है जब उपवर्ग पूरी तरह से परिभाषित होता है।
ऊपर दी गई तालिका की व्याख्या निम्न तरीके से की गई है (पहली पंक्ति पर एक नज़र डालें):
यदि एक घटक है घोषित रूप में सार्वजनिक और अपने वर्ग है विरासत में मिला के रूप में सार्वजनिक जिसके परिणामस्वरूप पहुंच है जनता ।
एक उदाहरण:
class Super {
public: int p;
private: int q;
protected: int r;
};
class Sub : private Super {};
class Subsub : public Sub {};
चर के लिए जिसके परिणामस्वरूप पहुँच p
, q
, r
कक्षा में Subsub है कोई भी ।
एक और उदाहरण:
class Super {
private: int x;
protected: int y;
public: int z;
};
class Sub : protected Super {};
चर के लिए जिसके परिणामस्वरूप पहुँच y
, z
कक्षा में उप है संरक्षित और चर के लिए x
है कोई भी ।
एक अधिक विस्तृत उदाहरण:
class Super {
private:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
int main(void) {
Super object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
अब एक उपवर्ग को परिभाषित करने देता है:
class Sub : Super { };
int main(void) {
Sub object;
object.put(100);
object.put(object.get());
cout << object.get() << endl;
return 0;
}
उप नाम से परिभाषित वर्ग जो वर्ग नाम का उपवर्ग है Super
या उस Sub
वर्ग को वर्ग से लिया गया है Super
। Sub
नई चर और न ही नए कार्यों न वर्ग परिचय देता है। क्या इसका मतलब यह है कि Sub
वर्ग की कोई भी वस्तु Super
वास्तव में Super
वर्ग की वस्तुओं की नकल होने के बाद वर्ग के सभी लक्षणों को विरासत में देती है ?
नहीं । यह नहीं है
यदि हम निम्नलिखित कोड को संकलित करते हैं, तो हमें यह कहते हुए put
और संकलन त्रुटियों के अलावा कुछ भी नहीं मिलेगा कि get
तरीके अप्राप्य हैं। क्यों?
जब हम दृश्यता विनिर्देश को छोड़ देते हैं, तो संकलक मानता है कि हम तथाकथित निजी विरासत को लागू करने जा रहे हैं । इसका अर्थ है कि सभी सार्वजनिक सुपरक्लास घटक निजी पहुंच में बदल जाते हैं , निजी सुपरक्लास घटक सभी तक पहुँच योग्य नहीं होंगे। इसके फलस्वरूप इसका मतलब है कि आपको उपवर्ग के अंदर उत्तरार्द्ध का उपयोग करने की अनुमति नहीं है।
हमें संकलक को सूचित करना होगा कि हम पहले उपयोग की गई नीति को संरक्षित करना चाहते हैं।
class Sub : public Super { };
गुमराह न हों : इसका मतलब यह नहीं है कि सुपर क्लास (भंडारण चर की तरह) के निजी घटक सार्वजनिक रूप से कुछ जादुई तरीके से बदल जाएंगे। निजी घटकों रहेगा निजी , सार्वजनिक रहेगा सार्वजनिक ।
Sub
कक्षा की वस्तुएँ कक्षा से निर्मित अपने बड़े भाई-बहनों के समान ही "लगभग" काम कर सकती हैं Super
। "लगभग" क्योंकि उपवर्ग होने का तथ्य यह भी है कि वर्ग ने सुपरक्लास के निजी घटकों तक पहुंच खो दी । हम उस Sub
वर्ग के सदस्य फ़ंक्शन को नहीं लिख सकते हैं जो सीधे स्टोरेज वेरिएबल में हेरफेर करने में सक्षम होगा।
यह एक बहुत गंभीर प्रतिबंध है। क्या कोई वर्कअराउंड है?
जी हां ।
तीसरे पहुंच स्तर को संरक्षित कहा जाता है । संरक्षित कीवर्ड का मतलब है कि इसके साथ चिह्नित घटक किसी भी उपवर्ग द्वारा उपयोग किए जाने पर एक सार्वजनिक की तरह व्यवहार करता है और दुनिया के बाकी हिस्सों में निजी की तरह दिखता है । - यह केवल सार्वजनिक रूप से विरासत में मिली कक्षाओं (हमारे उदाहरण में सुपर क्लास की तरह) के लिए सही है -
class Super {
protected:
int storage;
public:
void put(int val) { storage = val; }
int get(void) { return storage; }
};
class Sub : public Super {
public:
void print(void) {cout << "storage = " << storage;}
};
int main(void) {
Sub object;
object.put(100);
object.put(object.get() + 1);
object.print();
return 0;
}
जैसा कि आप उदाहरण कोड में देखते हैं कि हम Sub
कक्षा के लिए एक नई कार्यक्षमता है और यह एक महत्वपूर्ण काम करता है: यह सुपर क्लास से स्टोरेज चर तक पहुंचता है ।
यह संभव नहीं होगा यदि चर को निजी घोषित किया गया हो। मुख्य फ़ंक्शन स्कोप में चर वैसे भी छिपा रहता है, जैसे कि आप कुछ भी लिखते हैं:
object.storage = 0;
संकलक आपको सूचित करेगा कि यह एक है error: 'int Super::storage' is protected
।
अंत में, अंतिम प्रोग्राम निम्न आउटपुट का उत्पादन करेगा:
storage = 101
यह करना है कि कैसे व्युत्पन्न वर्ग से आधार वर्ग के सार्वजनिक सदस्यों को उजागर किया जाता है।
जैसा कि लिटब इंगित करता है, सार्वजनिक विरासत पारंपरिक विरासत है जिसे आप अधिकांश प्रोग्रामिंग भाषाओं में देखेंगे। यह एक "आईएस-ए" संबंध मॉडल है। निजी विरासत, C ++ के लिए AFAIK अजीब, एक "संबंध के मामले में निहित" है। आप व्युत्पन्न वर्ग में सार्वजनिक इंटरफ़ेस का उपयोग करना चाहते हैं , लेकिन नहीं चाहते कि व्युत्पन्न वर्ग के उपयोगकर्ता को उस इंटरफ़ेस तक पहुंच प्राप्त हो। कई लोग तर्क देते हैं कि इस मामले में आपको आधार वर्ग को एकत्रित करना चाहिए, जो कि आधार वर्ग को एक निजी आधार के रूप में रखने के बजाय, आधार वर्ग की कार्यक्षमता का पुन: उपयोग करने के लिए व्युत्पन्न सदस्य में करें।
Member in base class : Private Protected Public
वंशानुक्रम प्रकार : वस्तु के रूप में विरासत में मिला :
Private : Inaccessible Private Private
Protected : Inaccessible Protected Protected
Public : Inaccessible Protected Public
1) सार्वजनिक विरासत :
ए। बेस क्लास के निजी सदस्य व्युत्पन्न वर्ग में पहुँच योग्य नहीं हैं।
ख। बेस क्लास के संरक्षित सदस्य व्युत्पन्न वर्ग में संरक्षित रहते हैं।
सी। बेस वर्ग के सार्वजनिक सदस्य व्युत्पन्न वर्ग में सार्वजनिक रहते हैं।
तो, अन्य वर्ग डेरिव्ड क्लास ऑब्जेक्ट के माध्यम से बेस क्लास के सार्वजनिक सदस्यों का उपयोग कर सकते हैं।
2) संरक्षित वंशानुक्रम :
ए। बेस क्लास के निजी सदस्य व्युत्पन्न वर्ग में पहुँच योग्य नहीं हैं।
ख। बेस क्लास के संरक्षित सदस्य व्युत्पन्न वर्ग में संरक्षित रहते हैं।
सी। बेस क्लास के सार्वजनिक सदस्य भी व्युत्पन्न वर्ग के संरक्षित सदस्य बन जाते हैं।
इसलिए, अन्य वर्ग बेस क्लास के सार्वजनिक सदस्यों को व्युत्पन्न वर्ग वस्तु के माध्यम से उपयोग नहीं कर सकते हैं; लेकिन वे व्युत्पन्न के उपवर्ग के लिए उपलब्ध हैं।
3) निजी विरासत :
ए। बेस क्लास के निजी सदस्य व्युत्पन्न वर्ग में पहुँच योग्य नहीं हैं।
ख। बेस क्लास के संरक्षित और सार्वजनिक सदस्य व्युत्पन्न वर्ग के निजी सदस्य बन जाते हैं।
इसलिए, बेस क्लास के किसी भी सदस्य को Derived क्लास ऑब्जेक्ट के माध्यम से अन्य वर्गों द्वारा एक्सेस नहीं किया जा सकता है क्योंकि वे Derived क्लास में निजी हैं। इसलिए, व्युत्पन्न वर्ग का उपवर्ग भी उन तक नहीं पहुंच सकता है।
सार्वजनिक विरासत एक IS-A संबंध मॉडल है। साथ में
class B {};
class D : public B {};
हर D
एक है B
।
निजी विरासत एक IS-IMPLEMENTED-USING संबंध (या जो भी कहा जाता है) को मॉडल करता है। साथ में
class B {};
class D : private B {};
a D
एक नहीं है B
, बल्कि हर कोई इसके कार्यान्वयन में D
उपयोग करता B
है। निजी विरासत को हमेशा इसके बजाय रोकथाम का उपयोग करके समाप्त किया जा सकता है:
class B {};
class D {
private:
B b_;
};
यह D
भी, B
इस मामले में, इसका उपयोग करके लागू किया जा सकता है b_
। वंशानुक्रम की तुलना में प्रकारों के बीच कम तंग युग्मन है, इसलिए सामान्य तौर पर इसे प्राथमिकता दी जानी चाहिए। कभी-कभी निजी विरासत के बजाय रोकथाम का उपयोग करना निजी विरासत के रूप में सुविधाजनक नहीं है। अक्सर यह आलसी होने का एक बहाना है।
मुझे नहीं लगता कि किसी को पता है कि protected
इनहेरिटेंस मॉडल क्या हैं। कम से कम मैंने अभी तक कोई ठोस व्याख्या नहीं देखी है।
D
निजी रूप से प्राप्त होता है D
, तो यह वर्चुअल फ़ंक्शन को ओवरराइड कर सकता है B
। (यदि, उदाहरण के लिए, B
एक पर्यवेक्षक इंटरफ़ेस है, तो D
इसे लागू कर सकते हैं और this
एक इंटरफ़ेस की आवश्यकता वाले कार्यों को पास कर सकते हैं , हर D
किसी को पर्यवेक्षक के रूप में उपयोग करने में सक्षम होने के बिना ।) इसके अलावा, D
चुनिंदा सदस्यों को B
इसके इंटरफ़ेस में उपलब्ध करा सकता है using B::member
। B
सदस्य होने पर लागू करने के लिए दोनों को सिंथेटिक रूप से असुविधाजनक है ।
protected
विरासत मुझे एक virtual
बेस क्लास और protected
ctor के साथ उपयोगी मिली है :struct CommonStuff { CommonStuff(Stuff*) {/* assert !=0 */ } }; struct HandlerMixin1 : protected virtual CommonStuff { protected: HandlerMixin1() : CommonStuff(nullptr) {} /*...*/ }; struct Handler : HandlerMixin1, ... { Handler(Stuff& stuff) : CommonStuff(&stuff) {} };
यदि आप सार्वजनिक रूप से किसी अन्य वर्ग से विरासत में प्राप्त करते हैं, तो हर कोई जानता है कि आप विरासत में मिले हैं और आप बेस क्लास पॉइंटर के माध्यम से किसी के द्वारा पॉलीमॉर्फिक रूप से उपयोग किए जा सकते हैं।
यदि आप सुरक्षित रूप से विरासत में प्राप्त करते हैं, तो केवल आपके बच्चे वर्ग ही आपको बहुरूपिक रूप से उपयोग करने में सक्षम होंगे।
यदि आप निजी तौर पर केवल विरासत में हैं तो माता-पिता के तरीकों को निष्पादित करने में सक्षम होंगे।
जो मूल रूप से इस ज्ञान का प्रतीक है कि बाकी कक्षाएं आपके मूल वर्ग के साथ आपके रिश्ते के बारे में हैं
संरक्षित डेटा सदस्यों को आपके वर्ग से प्राप्त किसी भी वर्ग द्वारा पहुँचा जा सकता है। निजी डेटा सदस्य, हालांकि, नहीं कर सकते। मान लें कि हमारे पास निम्नलिखित हैं:
class MyClass {
private:
int myPrivateMember; // lol
protected:
int myProtectedMember;
};
इस श्रेणी में आपके एक्सटेंशन के भीतर से, संदर्भित this.myPrivateMember
कार्य नहीं करेगा। हालाँकि, this.myProtectedMember
होगा। मान अभी भी एनकैप्सुलेटेड है, इसलिए यदि हमारे पास इस वर्ग की तात्कालिकता है जिसे कहा जाता है myObj
, तो myObj.myProtectedMember
काम नहीं करेगा, इसलिए यह एक निजी डेटा सदस्य के लिए फ़ंक्शन के समान है।
Accessors | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public | y | y | y
—————————————+————————————+———————————————+———————
protected | y | y | n
—————————————+————————————+———————————————+———————
private | | |
or | y | n | n
no accessor | | |
y: accessible
n: not accessible
जावा के लिए इस उदाहरण के आधार पर ... मुझे लगता है कि एक हजार शब्दों की एक छोटी सी तालिका :)
एक आधार वर्ग के निजी सदस्यों को केवल उस आधार वर्ग के सदस्यों द्वारा ही पहुँचा जा सकता है।
एक बेस क्लास के सार्वजनिक सदस्यों को उस बेस क्लास के सदस्यों, उसके व्युत्पन्न वर्ग के सदस्यों के साथ-साथ उन सदस्यों तक पहुँचा जा सकता है जो बेस क्लास और व्युत्पन्न वर्ग के बाहर हैं।
बेस क्लास के संरक्षित सदस्यों को बेस क्लास के सदस्यों के साथ-साथ उसके व्युत्पन्न वर्ग के सदस्यों द्वारा भी एक्सेस किया जा सकता है।
निजी : आधार
संरक्षित : आधार + व्युत्पन्न
सार्वजनिक : आधार + व्युत्पन्न + कोई अन्य सदस्य
मुझे एक आसान जवाब मिला और इसलिए मैंने इसे अपने भविष्य के संदर्भ के लिए पोस्ट करने के बारे में सोचा।
इसके लिंक से http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
class Base
{
public:
int m_nPublic; // can be accessed by anybody
private:
int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
int m_nProtected; // can be accessed by Base member functions, or derived classes.
};
class Derived: public Base
{
public:
Derived()
{
// Derived's access to Base members is not influenced by the type of inheritance used,
// so the following is always true:
m_nPublic = 1; // allowed: can access public base members from derived class
m_nPrivate = 2; // not allowed: can not access private base members from derived class
m_nProtected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base cBase;
cBase.m_nPublic = 1; // allowed: can access public members from outside class
cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}
यह मूल रूप से व्युत्पन्न वर्ग में आधार वर्ग के सार्वजनिक और संरक्षित सदस्यों की पहुंच सुरक्षा है। सार्वजनिक विरासत के साथ, व्युत्पन्न वर्ग आधार के सार्वजनिक और संरक्षित सदस्यों को देख सकता है। निजी विरासत के साथ, यह नहीं हो सकता। संरक्षित के साथ, व्युत्पन्न वर्ग और उस से प्राप्त किसी भी वर्ग उन्हें देख सकते हैं।