2011-11-04 10 views
35

नीचे कहा जाता है कि सार्वजनिक सदस्यों के रूप में पहले/दूसरे होने के बाद नीचे बेहतर कहा जाता है। मेरा मानना ​​है कि यह लगभग उतना ही बुरा है। यदि आप कक्षा के बाहर एक निजी चर का उपयोग करने का कोई तरीका दे रहे हैं तो बिंदु क्या है? नहीं कार्योंसदस्य चर के खराब अभ्यास का संदर्भ वापस कर रहा है?

T First(); void(or T) First(const T&) 

नमूना होना चाहिए: बड़ा संरचनाओं

// Example 17-3(b): Proper encapsulation, initially with inline accessors. Later 
// in life, these might grow into nontrivial functions if needed; if not, then not. 
// 
template<class T, class U> 
class Couple { 
    Couple()   : deleted_(false) { } 
    T& First()   { return first_; } 
    U& Second()  { return second_; } 
    void MarkDeleted() { deleted_ = true; } 
    bool IsDeleted() { return deleted_; } 

private: 
T first_; 
U second_; 
bool deleted_; 
}; 

उत्तर

43

कक्षा के आंतरिक भाग में संदर्भ (या पॉइंटर्स) लौटने के कई कारण हैं। के साथ शुरू (मैं क्या करने पर विचार) सबसे महत्वपूर्ण:

  1. Encapsulation का उल्लंघन होता है: यदि आप एक कार्यान्वयन विस्तार, जिसका अर्थ है कि आप अब अपने वर्ग internals बदल के रूप में आप चाहते हैं कर सकते हैं रिसाव। यदि आपने उदाहरण के लिए first_ स्टोर न करने का निर्णय लिया है, लेकिन इसे फ्लाई पर गणना करने के लिए, तो आप इसका संदर्भ कैसे वापस लाएंगे? आप नहीं कर सकते, इस प्रकार आप फंस गए हैं।

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

  3. लाइफटाइम समस्याएं उभरती हैं: मूल ऑब्जेक्ट के बाद वे मौजूद वस्तु के संदर्भ में संदर्भ या पॉइंटर रखना आसान है। यह निश्चित रूप से अपरिभाषित व्यवहार है। अधिकांश कंपाइलर स्टैक पर ऑब्जेक्ट्स के संदर्भों को रखने के बारे में चेतावनी देने का प्रयास करेंगे, उदाहरण के लिए, लेकिन मुझे कोई कंपाइलर नहीं पता है जो फ़ंक्शंस या विधियों द्वारा दिए गए संदर्भों के लिए ऐसी चेतावनियां उत्पन्न करने में कामयाब रहा: आप स्वयं ही हैं।

इस प्रकार, आमतौर पर संदर्भों या पॉइंटर्स को गुणों को दूर नहीं करना बेहतर होता है। यहां तक ​​कि एक भी नहीं है!

छोटे मान के लिए, यह कदम अर्थ विज्ञान (में रास्ते पर) के साथ विशेष रूप से अब आम तौर पर उन्हें प्रति द्वारा पारित करने के लिए पर्याप्त (दोनों in और out), है।

बड़े मूल्यों के लिए, यह वास्तव में स्थिति पर निर्भर करता है, कभी-कभी प्रॉक्सी आपकी परेशानियों को कम कर सकता है।

अंत में, ध्यान दें कि कुछ वर्गों के लिए, सार्वजनिक सदस्य होने के कारण इतना बुरा नहीं है।pair के सदस्यों को encapsulating का मुद्दा क्या होगा? जब आप खुद को ऐसी कक्षा लिखते हैं जो गुणों के संग्रह (कोई भी परिवर्तनीय नहीं) से अधिक नहीं है, तो हमारे ऊपर सभी ओओ प्राप्त करने और उनमें से प्रत्येक के लिए गेटर/सेटर जोड़ी लिखने के बजाय, उन्हें सार्वजनिक बनाने पर विचार करें।

+2

+1, लेकिन एक्सेसर्स प्रदान करने के लिए एक काउंटर तर्क है: आप कॉल में उपकरण जोड़ सकते हैं और इससे कोड को ऑब्जेक्ट में अपडेट किया जा रहा है, या मुद्दों का पता लगाने के लिए डीबगर संलग्न करना आसान बनाता है। –

+1

आपके लिए जानकारी उन उदाहरणों के बारे में बात कर रही थी, जिनमें निजी सदस्य हैं इसलिए 'बूल हटाया गया'; मुझे पीओडी –

+0

@ डेविड पसंद है: मैं टी टी()/शून्य सेट (टी) 'में एक्सेसर्स के खिलाफ नहीं हूं, जिसमें आप प्रभावी रूप से अपने मूल्यों के परिवर्तनों को ट्रैक कर सकते हैं, आलसी गणना और अन्य चीजों को प्रदान कर सकते हैं, लेकिन 'टी और एक्सेस() 'में केवल रोचक टिडबिट" ट्रेस "है कि एक एक्सेस बनाया गया था, जो तालिका में ज्यादा नहीं लाता है। –

17

तो template प्रकार T और U तो वापसी मान से महंगा है। हालांकि आप सही हैं कि संदर्भ द्वारा लौटने से private चर तक पहुंच प्रदान करने के बराबर है।

const T& First() const { return first_; } 
const U& Second() const { return second_; } 

पी.एस.: दोनों मुद्दों को हल करने के लिए, उन्हें const संदर्भ बनाने इसके अलावा, जब कोई सेटर विधि नहीं है, तो कन्स्ट्रक्टर के भीतर वैरिएबल को अनियंत्रित रखने के लिए यह एक बुरा अभ्यास है। ऐसा लगता है कि मूल कोड में, First() और Second()first_ और second_ पर रैपर हैं जो दोनों को पढ़ने/लिखने के लिए थे।

+0

आह हा, अच्छा समाधान। जब तक पढ़ता है ('प्रथम() ') का दुष्प्रभाव होता है तो यह पूरी तरह से ठीक होगा (एक अनुचित प्रतिबंध नहीं है लेकिन अभी भी एक प्रतिबंध है :)) –

+2

+1। अच्छा ........ – Nawaz

+3

[यह लिंक] (http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) मूल्य से गुजरने में कुछ रोचक अंतर्दृष्टि है और आर मूल्यों। – juanchopanza

6

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

std::map<int,std::string> a; 
a[1] = 1; 

कुछ भी नहीं करने के लिए संदर्भ देता है

auto & aref = a[1]; 

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

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