एक ही वर्ग की वस्तुओं का एक-दूसरे के निजी डेटा तक पहुंच क्यों है?


99

एक ही वर्ग की वस्तुओं का एक-दूसरे के निजी डेटा तक पहुंच क्यों है?

class TrivialClass {
public: 
  TrivialClass(const std::string& data) :
    mData(data) {};

  const std::string& getData(const TrivialClass& rhs) const {
    return rhs.mData;
  };

private:
  std::string mData;
};

int main() {
  TrivialClass a("fish");
  TrivialClass b("heads");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}

यह कोड काम करता है। ऑब्जेक्ट b से निजी डेटा एक्सेस करने और उसे वापस करने के लिए ऑब्जेक्ट के लिए यह पूरी तरह से संभव है। यह ऐसा क्यों होना चाहिए? मुझे लगता है कि निजी डेटा निजी है। (मैंने पिंपल मुहावरे में कॉपी कंस्ट्रक्टर्स को समझने की कोशिश करके शुरुआत की थी, लेकिन तब मुझे पता चला कि मैंने इस सरल स्थिति को भी नहीं समझा है।)


18
ठीक है, एक शुरुआती बिंदु के रूप में, आप किसी भी चीज़ के लिए किसी भी कॉपी-कंस्ट्रक्टर को ठीक से लागू नहीं कर पाएंगे लेकिन सबसे सरल वर्ग। आप कक्षाओं को अपना सबसे अच्छा दोस्त होने के बारे में सोच सकते हैं :-)
कैमरन

4
अपने ग्राहकों से निजी के बारे में सोचें, लेकिन कक्षा के सभी कर्मचारियों तक पहुंच है
मार्टिन बेकेट

धन्यवाद कैमरन। यह समझ में आता है, लेकिन फिर यह पहुंच केवल निर्माणकर्ताओं और असाइनमेंट ऑपरेटरों की नकल तक ही सीमित क्यों नहीं है?
कीथ

5
एक ही प्रकार की वस्तुएं अक्सर बहुत कुछ करती हैं। और कोई भी आपको एक ऐसी विधि लिखने के लिए मजबूर नहीं कर रहा है जो किसी अन्य उदाहरण के निजी डेटा को सौंपती है। :)
अंकलबीन्स

4
केवल इसलिए, संकलन के समय, संकलक के पास अपनी समान वस्तु को पहचानने का कोई तरीका नहीं होता है। ऐसी पहुंच को लागू करने के लिए रन-टाइम समर्थन की आवश्यकता होगी।
चेतन

जवाबों:


80

क्योंकि यही C ++ में काम करता है। C ++ में अभिगम नियंत्रण प्रति-वर्ग के आधार पर काम करता है , प्रति-वस्तु के आधार पर नहीं।

C ++ में अभिगम नियंत्रण को एक स्थिर, संकलन-समय सुविधा के रूप में लागू किया गया है। मुझे लगता है कि यह स्पष्ट है कि संकलन समय पर किसी भी सार्थक प्रति-वस्तु अभिगम नियंत्रण को लागू करना वास्तव में संभव नहीं है। केवल प्रति-वर्ग नियंत्रण उस तरह से लागू किया जा सकता है।

प्रति-ऑब्जेक्ट नियंत्रण के कुछ संकेत संरक्षित एक्सेस विनिर्देश में मौजूद हैं , यही वजह है कि मानक (11.5) में इसका अपना समर्पित अध्याय भी है। लेकिन फिर भी वहाँ वर्णित किसी भी प्रति-वस्तु सुविधाएँ बल्कि अल्पविकसित हैं। फिर, C ++ में अभिगम नियंत्रण प्रति वर्ग के आधार पर काम करने के लिए है।


9
+1। C ++ संकलन-समय तंत्र पर बड़ा है, रन-टाइम तंत्र पर इतना बड़ा नहीं है। बहुत अच्छा सामान्य नियम।
निमो

4
आपका "संकलन समय पर किसी भी सार्थक प्रति-वस्तु अभिगम नियंत्रण को लागू करना वास्तव में संभव नहीं है"। क्यों नहीं? में void X::f(X&x), संकलक आसानी से भेद करने में सक्षम है this->aऔर x.a। यह जानने के लिए संकलक के लिए यह (हमेशा) संभव नहीं है *thisऔर xवास्तव में एक ही वस्तु है यदि x.f(x)इसे लागू किया जाता है, लेकिन मैं एक भाषा डिजाइनर को इस ओके को अच्छी तरह से देख सकता था।
एंड्रे कारन

@ AndréCaron मुझे लगता है कि यह वास्तव में मछली की केतली का एक बहुत बड़ा है तो आप इसे बाहर करने के लिए बनाते हैं। जब इनलाइनिंग नहीं होती है तो कंपाइलर को हमेशा एक चेक करना होगा कि क्या thisऔर &xवही हैं। यह और भी बुरा यह वास्तव में भी साथ कोई समस्या किया जा रहा समाप्त होता है बनाने के लिए X::f(Y& y), क्योंकि हमारे ठोस ऑब्जेक्ट प्रकार का हो सकता है Zकि दोनों से विरासत में मिली Xऔर Y। संक्षेप में, यह एक वास्तविक गड़बड़ है, प्रदर्शन करने वाला नहीं, एमआई के साथ समझदारी से काम करने के लिए कठिन।
निर फ्राइडमैन

@NirFriedman मुझे लगता है कि आप सुझाव को गलत समझते हैं। संकलन करते समय X::f(X& x), अगर वहाँ पहुँच रहे हैं x.a, यह संकलन नहीं होगा। और कुछ नहीं बदलता है, कोई चेक सम्मिलित करने की आवश्यकता नहीं है, इसलिए अभी भी मान्य कार्यक्रमों का प्रदर्शन प्रभावित नहीं होता है। और इसे मौजूदा C ++ में ब्रेकिंग चेंज के रूप में नहीं सुझाया गया है, लेकिन privateमूल रूप से पेश करते समय डिजाइनर कुछ ऐसा कर सकते हैं ।
एलेक्सी रोमानोव

31

"प्राइवेट" वास्तव में एक एक्सेस कंट्रोल मैकेनिज्म नहीं है, "मैंने फेसबुक पर अपनी तस्वीरें निजी तौर पर बनाईं ताकि आप उन्हें देख न सकें।"

C ++ में, "निजी" बस यह कहता है कि ये एक ऐसे वर्ग के हिस्से हैं जिन्हें आप (कक्षा का कोडर) भविष्य के संस्करणों में बदल सकते हैं, आदि, और आप नहीं चाहते कि आपके कोड का उपयोग उनके अस्तित्व या कार्यक्षमता पर भरोसा करने के लिए करें। ।

यदि आप सही अभिगम नियंत्रण चाहते हैं, तो आपको वास्तविक डेटा सुरक्षा तकनीकों को लागू करना चाहिए।


13

यह एक अच्छा सवाल है और मैं हाल ही में इस सवाल पर आया हूं। मैंने अपने सहयोगियों के साथ कुछ चर्चाएँ कीं और यहाँ हमारी चर्चा का सारांश है: यह डिज़ाइन द्वारा है। इसका मतलब यह नहीं है कि यह डिजाइन सभी मामलों के लिए पूरी तरह से उचित है, लेकिन कुछ विचार होना चाहिए कि प्रति वर्ग निजी क्यों चुना जाता है। जिन संभावित कारणों के बारे में हम सोच सकते हैं उनमें शामिल हैं:

सबसे पहले, प्रति उदाहरण पहुंच नियंत्रण की लागत बहुत अधिक हो सकती है। इस धागे में दूसरों द्वारा चर्चा की गई है। सिद्धांत रूप में, यह इस पॉइंटर चेक के माध्यम से किया जा सकता है । हालाँकि, यह संकलन समय पर नहीं किया जा सकता है, और केवल रन समय पर किया जा सकता है। इसलिए आपको रन टाइम में प्रत्येक सदस्य के अभिगम नियंत्रण की पहचान करनी होगी, और जब इसका उल्लंघन होगा तो संभवतः केवल अपवाद ही उठाए जाएंगे। लागत अधिक है।

दूसरे, प्रति वर्ग अभिगम नियंत्रण का अपना उपयोग मामला होता है, जैसे कॉपी कंस्ट्रक्टर या ऑपरेटर =। यदि पहुंच नियंत्रण प्रति उदाहरण है तो उन्हें लागू करना कठिन होगा।

साथ ही, एक्सेस कंट्रोल मुख्य रूप से प्रोग्रामिंग / लैंग्वेज के नजरिए से होता है, कोड / सदस्य तक एक्सेस को मॉड्युलर / कंट्रोल कैसे किया जाए, इसके लिए डेटा नहीं।


12

यह कुछ हद तक एक मनमाना भाषा डिजाइन निर्णय है। में रूबी , उदाहरण के लिए, privateवास्तव में निजी है, जिसका अर्थ में "एकमात्र उदाहरण अपनी निजी डेटा सदस्यों तक पहुँच सकते हैं"। हालांकि, यह कुछ हद तक प्रतिबंधात्मक है।

जैसा कि टिप्पणियों में कहा गया है, कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर सामान्य स्थान हैं जहां आप किसी अन्य उदाहरण के निजी डेटा सदस्यों को सीधे एक्सेस करते हैं। इसके कम स्पष्ट कारण हैं।

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


4

चाल को याद है कि डेटा है privateकरने के लिए वर्ग , नहीं उदाहरण वर्ग की। आपकी कक्षा के भीतर कोई भी विधि उस वर्ग के किसी भी उदाहरण के निजी डेटा तक पहुंच सकती है; जब तक आप स्पष्ट रूप से अन्य उदाहरणों के निजी डेटा सदस्यों तक पहुँचने के तरीकों को मना नहीं करते हैं, उदाहरण के भीतर डेटा को निजी रखने का एक तरीका नहीं है।


1

उपरोक्त सभी उत्तरों के अलावा, कस्टम कॉपी कंस्ट्रक्टर, असाइनमेंट ऑपरेटर और अन्य सभी कार्यों पर विचार करें जो आप एक वर्ग के लिए लिखेंगे जो अन्य उदाहरणों पर काम करते हैं । आपको उन सभी डेटा सदस्यों के लिए एक्सेसर कार्यों की आवश्यकता होगी।


-8

निजी डेटा तब तक निजी रहता है जब तक कि किसी के पास इसका उपयोग दूसरे के लिए नहीं होता है।

यह अवधारणा अन्य स्थिति पर भी लागू होती है, जैसे:

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};

कोई कैसे पैसे निकाल सकता है? :)


3
इस उदाहरण में अन्य उदाहरण के निजी डेटा सदस्यों तक पहुँचने वाले एक वर्ग के उदाहरण शामिल नहीं हैं।
एंड्रे कैरन

@Andre, "यह अवधारणा अन्य स्थिति पर भी लागू होती है, जैसे ..."
YeenFei

^ "अन्य स्थिति" परिभाषा के अनुसार ऑफ-टॉपिक हैं, इसलिए आपका उदाहरण बिना किसी प्रासंगिकता के है (और मुझे यकीन नहीं है कि यह कहीं और भी जानकारीपूर्ण होगा)
अंडरस्कोर_ड

1
यह प्रश्न के लिए सही व्याख्या नहीं है।
पांडा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.