2010-10-14 9 views
9

इस प्रश्न से पूछना क्योंकि मुझे लगता है कि मेरे आधार के सदस्य चर के बाद व्युत्पन्न कक्षाओं में आवश्यक होगा। क्या उन्हें सुरक्षित बनाने में कोई कमी है?क्या सदस्य चर सुरक्षित करने के लिए यह अच्छा अभ्यास है?

संपादित करें: मेरे इरादे को बेहतर ढंग से दिखाने के लिए संपादित किया गया।

संपादित करें: @ एसबीआई: क्या यह भी गलत है?

इस कक्षा का उपयोग अन्य रिकॉर्डिंग में त्रुटि रिकॉर्डिंग और पुनर्प्राप्ति के लिए किया जाएगा। क्या इससे बेहतर होना या इसकी वस्तु का उपयोग करना बेहतर है - मुझे नहीं पता। लेकिन मुझे लगता है कि गेटटर और सेटर विधियां इस वर्ग के बारे में क्या हैं।

class ErrorLogger 
{ 
    public: 
     //Making this function virtual is optional 
     virtual void SetError(const char*, ...); 
     const char* GetError() const; 
    protected: 
     char* z_ErrorBuf; 
}; 
+1

आपको क्यों लगता है कि बाद में व्युत्पन्न कक्षाओं में सदस्य चर की आवश्यकता होगी? उनके लिए क्या आवश्यकता होगी, और उन्हें उजागर करने की आवश्यकता क्यों होगी? –

उत्तर

21

Encapsulation ओओ की मुख्य विशेषताओं में से एक है। कक्षाओं में आपके डेटा को Encapsulating का मतलब है कि कक्षा के उपयोगकर्ता कक्षा के डेटा invariants तोड़ नहीं सकते हैं, क्योंकि वर्ग 'राज्य केवल अपने सदस्य कार्यों के माध्यम से छेड़छाड़ की जा सकती है।

यदि आप अपने आधार वर्ग के व्युत्पन्न वर्ग उपयोग की अनुमति डेटा की अपरिवर्तनशीलताओं 'डेटा, तो व्युत्पन्न वर्ग आधार वर्ग रद्द करने के लिए नहीं करने के लिए देखभाल करने के लिए की जरूरत है'। वह खिड़की से बाहर encapsulation फेंकता है और सिर्फ गलत है। (तो getters and setters, बीटीडब्लू।)

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

+0

और फिर भी आपको हमेशा निजी के रूप में चर बनाना चाहिए और संरक्षित गुण/एक्सेसर्स का उपयोग करना चाहिए। –

+2

@SoMoS: कृपया सेटर्स और गेटर्स के संबंध में लिंक किए गए दस्तावेज़ को देखें। वे एक घृणित हैं। – sbi

+1

@ सोमोस: मैं 107% से असहमत हूं। एक आर्किटेक्चर जो एक चर का उपयोग करने के लिए सरल गेटर्स और सेटर्स का उपयोग करता है वह मूर्खतापूर्ण है। बस शापित चीजें सार्वजनिक करें। क्या फर्क पड़ता है? –

2

मैं उत्सुक हूं कि अन्य लोग इसका क्या जवाब देंगे।

साथ ही एक्सेसर्स प्रतिमान के लिए, आप उन्हें निजी घोषित कर सकते हैं और संरक्षित गेटर और सेटर विधियों का उपयोग कर सकते हैं। यदि आपका बेस क्लास कार्यान्वयन बदलता है, तो आपके पास केवल उन गेटटर और सेटर को संशोधित करने के लिए है।

2

यदि आपको लगता है कि बाल कक्षाओं को बाद में उन चरों तक पहुंच की आवश्यकता होगी तो हाँ, उन्हें सुरक्षित बनाएं।

उपर्युक्त स्थिति पूरी होने तक कोई कमी नहीं है।

यदि आप अतिरिक्त कदम उठाना चाहते हैं और बाहरी चर से अपने चर की रक्षा करना चाहते हैं, तो आप हमेशा निजी सदस्य चर बना सकते हैं और फिर उन निजी चरों को एक्सेस/संशोधित करने के लिए संरक्षित विधियों का उपयोग कर सकते हैं।

2

विरासत कक्षा का उपयोग करने का एक और तरीका है। यह अधिक युग्मित है और आपके सदस्य चर को संरक्षित करके, आप और भी अधिक जोड़े हैं, इसलिए आपको प्रत्येक विरासत वर्ग पर प्रभाव जानने के बिना उन्हें नहीं बदला जाना चाहिए। यदि यह आपकी बेस-क्लास और आपकी विरासत वाली कक्षा है, तो शायद कोई नुकसान नहीं होने वाला है, लेकिन आप इस बात पर नियंत्रण खो देते हैं कि सदस्यों को कैसे पहुंचाया जाना चाहिए (लॉकिंग, लॉगिंग, पढ़ना/लिखना, दृढ़ता, ...)।

0

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

निर्णय लेने की सबसे महत्वपूर्ण बात यह है कि सार्वजनिक बनाम/निजी क्या है, क्योंकि जिस तरह से आप अपनी कक्षा को बाहरी दुनिया में पेश करते हैं।

1

संरक्षित डेटा में सार्वजनिक डेटा की सभी कमीएं हैं, इसलिए आप उन्हें सार्वजनिक भी कर सकते हैं।

1

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

यदि आप उन्हें सुरक्षित करते हैं और बाद में निर्णय लेते हैं कि निजी होना चाहिए, तो उन्हें बदलना मौजूदा कोड को तोड़ सकता है जो उन पर निर्भर करता है।

अंगूठे का मेरा व्यक्तिगत नियम सबकुछ निजी बनाना है और आवश्यकतानुसार दृश्यता श्रृंखला को बढ़ावा देना है।

1

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

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

+1

मानक सी ++ में कोई 'मुहरबंद' कीवर्ड नहीं है। –

+0

ओह, गलत टैग। खैर, एक ही विचार लेकिन शून्य * मुहरबंद *। –

+0

@downvoter - मुझे कीवर्ड खोने वाली भाषा के लिए दोष न दें। –

-1

एक सुरक्षित गेटर और शायद निजी आंतरिक चर के लिए सेटटर प्रदान करें, यह थोड़ा और कोड है, लेकिन यह बहुत साफ है।

0

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

+1

मैं असहमत हूं। एसबीआई के पोस्ट –

+1

@ जॉइन में टिप्पणी देखें: मैं यह भी समझ सकता हूं कि आप असहमत क्यों हैं। लेकिन मेरा मुद्दा यहां है "अगर" सार्वजनिक सदस्यों के लिए बुरा है, "फिर" संरक्षित सदस्यों के लिए यह बुरा है। लेकिन, वास्तव में, सार्वजनिक सदस्यों के लिए स्पष्ट प्रतिबंध बहस योग्य है। –

+0

आह, मैं देखता हूं कि अब आप क्या कह रहे हैं। –

1

कुछ 'सार्वजनिक' बनाना एक अनुबंध बनाता है जो सभी विरासत कक्षाओं पर बाध्यकारी होगा। कुछ 'संरक्षित' बनाना सीधे -हित कक्षाओं के साथ अनुबंध बनाता है, लेकिन वर्गों को उनके किसी भी वंशज को ऐसा अनुबंध उपलब्ध कराने के लिए मजबूर नहीं करता है।

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

यदि कोई उम्मीद करता है कि व्युत्पन्न कक्षाएं उन परिस्थितियों में बनाई जा सकती हैं जहां पदानुक्रम में उनके ऊपर की कक्षाएं पूरी तरह से ज्ञात नहीं हैं या अपरिवर्तनीय नहीं हैं, तो यह संरक्षक गेटर्स/सेटर्स को सुरक्षित रखने के लिए अधिक उपयुक्त हो सकता है, लेकिन यह जिम्मेदारी हो सकती है जो भी पदानुक्रम में 'अपारदर्शी' परत बनाता है के साथ छोड़ दिया।

उदाहरण: एक संग्रह 'गिनती' नामक फ़ील्ड को बनाए रख सकता है। संग्रह का एक मूल संस्करण चीजों को इस तरह से स्टोर कर सकता है जो हमेशा उस क्षेत्र को बनाए रखना आसान बनाता है जो हमेशा वस्तुओं की संख्या रखता है, लेकिन व्युत्पन्न संस्करण चीजों को इस तरह से स्टोर कर सकता है जिससे यह मुश्किल हो जाता है। "गिनती" नामक एक क्षेत्र बनाकर, बेस क्लास अपने प्रत्यक्ष वंशजों का वादा करता है कि वह उस क्षेत्र में वस्तुओं की संख्या बनाए रखेगा। एक व्युत्पन्न वर्ग चीजों को अलग-अलग स्टोर कर सकता है, जैसे "गिनती" क्षेत्र सार्थक नहीं था।ऐसी कक्षा केवल पढ़ने-योग्य संपत्ति के साथ गिनती क्षेत्र को छाया दे सकती है; इसके वंशजों को पता होगा कि उन्हें एक संपत्ति पढ़नी पड़ी, जबकि मूल वर्ग के वंशज यह जान लेंगे कि वे एक क्षेत्र पढ़ सकते हैं।

सबसे महत्वपूर्ण बात यह है कि कक्षा में संरक्षित चीजें केवल प्रत्यक्ष वंशजों के साथ अनुबंध बनाती हैं, और वे वंशज निर्णय ले सकते हैं कि उप-वंश के लिए एक समान अनुबंध उपलब्ध कराया जाए या नहीं।

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

2

व्यक्तिगत रूप से, मैं आमतौर पर protected से virtual चीजों के उपयोग को प्रतिबंधित करने का प्रयास करता हूं।

मैं protected के किसी अन्य उपयोग को public के समतुल्य समकक्ष मानता हूं। इस अर्थ में कि यदि आप एक गैर वर्चुअल संरक्षित विधि लिखते हैं, तो इसे लिखें जैसे कि यह सार्वजनिक था। एक क्षेत्र के लिए वही। यदि क्षेत्र सार्वजनिक था तो कुछ तोड़ देगा, अगर यह सुरक्षित है तो यह कुछ तोड़ देगा।

इसका मतलब यह नहीं है कि संरक्षित फ़ील्ड या गैर वर्चुअल विधि होना बुरा है, इसका मतलब है कि आपको सावधान रहना होगा और उनके उपयोग के साथ जानबूझ कर रहना होगा, और जान लें कि कोई, कहीं, उन चीजों का उपयोग कर सकता है और संभावित रूप से ब्रेक आपकी कक्षा बस इसे प्राप्त करके।

+0

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

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