2010-09-11 7 views
5

सी ++ में, एक कॉन्स विधि है जो एक गैर-कॉन्स्ट ऑब्जेक्ट में एक पॉइंटर लौटा रही है जिसे बुरी आदत माना जाता है? उदाहरण के लिए। निम्नलिखित विधियों पर विचार करें:सी ++ में, एक कॉन्स विधि है जो एक गैर-कॉन्स्ट ऑब्जेक्ट को पॉइंटर लौटाती है जिसे बुरी आदत माना जाता है?

// Makes perfect sense 
bool isActive() const { return m_isActive; } 

// Makes perfect sense, both consts ensure nothing is modified 
const SomeObject* someObject() const { return m_someObject; } 

// Makes perfect sense, no const because SomeObject is mutable, 
// thus MyClass is indirectly mutable 
SomeObject* someObject() { return m_someObject; } 

// Makes no sense, if you're just returning a pointer to a const object, 
// then the method should clearly be const since nothing can be modified 
const SomeObject* someObject() { return m_someObject; } 

अंतिम संयोजन मुझे पहेली करता है: क्या निम्न बुरी प्रथा माना जाता है?

SomeObject* someObject() const { return m_someObject; } 

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

const SomeObject* someObject() const { return m_someObject; } 
SomeObject* someObject() { return m_someObject; } 

वास्तविक दुनिया स्थिति: मैं एक स्मार्टफोन खेल है, जिसमें एक Game वर्ग है लिख रहा हूँ। Game वर्ग, कई तरीके है जिसके InputManager, AudioManager तरह उपयोगिता वर्गों के लिए संकेत वापसी, आदि

class Game 
{ 
public: 
    InputManager* inputManager() const { return m_inputManager; } 
    ... 

private: 
    InputManager* m_inputManager; 
    ... 
} 

यह बिल्कुल कोई मतलब है inputManager() स्थिरांक बनाने के लिए होता है के बाद से वस्तु यह रिटर्न नहीं है? (और नहीं होना चाहिए, InputManager जरूरतों के बाद से परिवर्तनशील के लिए अपने राज्य को अपडेट करने की होने के लिए, आदि)

या मैं और अधिक सही विधि के व्यवहार को प्रतिबिंबित करने के विधि के const संशोधक को दूर करना चाहिए? इस तरह अगर मेरे पास const Game था, तो मैं inputManager() पर कॉल नहीं कर सका और फिर Game के इनपुट मैनेजर के साथ गड़बड़ कर सकता था, भले ही Gameconst था।

उत्तर

3

यह इस बात पर निर्भर करता है कि गैर-कॉन्स्ट पॉइंटर कॉन्स्ट ऑब्जेक्ट के अंदर कुछ इंगित कर रहा है या फिर यह नई आवंटित स्मृति है जो परिवर्तनीय होने के लिए है।

ऐसी किसी चीज़ पर विचार करें जो एक स्ट्रिंग की एक प्रति लौटाता है; लौटाई गई प्रतिलिपि के लिए यह ठीक है, भले ही मूल स्ट्रिंग स्थिर हो। प्रतिलिपि का स्वामित्व विधि से कॉलिंग कोड में पास किया जा रहा है; यह सुनिश्चित करना कि प्रतिलिपि उचित रूप से नष्ट हो गई है, अब कॉलिंग कोड की समस्या है (संभवतः एक बहुत मामूली समस्या)।

हालांकि, एक कॉन्स ऑब्जेक्ट के अंदर से किसी चीज़ को गैर-कॉन्स्ट पॉइंटर वापस करने का एक बहुत बुरा विचार होगा।

+1

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

2

यह पूरी तरह स्वीकार्य है। एक कॉन्स विधि का अर्थ है कि आप उस ऑब्जेक्ट को संशोधित नहीं कर रहे हैं जिसकी विधि आप कॉल कर रहे हैं - यह किसी अन्य ऑब्जेक्ट के बारे में कुछ भी नहीं कहती है। बेशक, वह वस्तु "इस" का हिस्सा हो सकती है, या यह "यह" हो सकती है - लेकिन यह बिंदु से परे है।

सामान्य रूप से "कॉन्स्ट" 10 से अधिक वादा है, लेकिन अंतर्निहित विचार समान है - एक कॉन्स विधि कहती है कि "यह" स्थिर है, और यह सब कुछ है।

+1

ठीक है, यह भी इतना नहीं है कि यह 'स्थिर' है, इसलिए मैं इस विशेष विधि का उपयोग करके 'इस' को संशोधित नहीं करूंगा। मुझे लगता है कि आप इस पहले पैराग्राफ में क्या कह रहे हैं, लेकिन यह थोड़ा अस्पष्ट लग रहा था। कॉन्स आम तौर पर एक वादा है जो किसी विशेष साधन के माध्यम से कुछ नहीं बदलना है जिसे चिह्नित किया गया है। पॉइंटर-टू-कॉन्स, संदर्भ-से-कॉन्स इत्यादि के लिए, संदर्भित ऑब्जेक्ट अक्सर किसी अन्य संदर्भ के माध्यम से गैर-आधार होता है और इसके माध्यम से संशोधित होता है। सदस्य डेटा में कॉन्स संदर्भ अक्सर बिंदु में एक मामला होता है - एक वादा है कि कक्षा उस संदर्भ को संशोधित नहीं करेगी, लेकिन कुछ भी नहीं। – Steve314

0

मेरी राय में, सदस्य का सूचक लौटने का एक बुरा विचार है, चाहे वह हो या नहीं।

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

+1

यदि आपकी कक्षा का कोई उपयोगकर्ता आपके द्वारा रखी गई सुरक्षा को रोकने के लिए 'const_cast' का उपयोग करता है, तो वे जो भी परेशानी प्राप्त करते हैं उसके लायक हैं। –

+0

@ डेनिस मैं पूरी तरह से सहमत हूं। एक साइड-नोट के रूप में, मैं उन लोगों को एक और प्रतिक्रिया देता हूं जो सी # और जावा जैसी भाषाओं को 'कॉन्स्ट' नहीं मानते हैं, एक अच्छा बात ™ है जब वे कहते हैं कि 'कॉन्स्ट' बेकार है क्योंकि लोग 'const_cast'' प्रतिबिंब का उपयोग कर सकते हैं। एक शब्द। :) –

0

मुझे नहीं लगता कि const यहां अधिक मायने रखता है।

यह सामान्य रूप से एक विशेषता के लिए एक हैंडल (सूचक, संदर्भ) वापस जाने के लिए पर फेंक दिया है:

  • यह एक particuler कार्यान्वयन के लिए उपयोगकर्ताओं को बांध, यह असंभव यह
  • बदलने के लिए यह लागू करने के लिए असंभव बना देता है अपरिवर्तनशीलताओं (गैर स्थिरांक संस्करण), अब आप इस तरह नहीं हो सकता है, लेकिन अब आप कभी नहीं है कि भविष्य

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

उदाहरण:

class Foo 
{ 
public: 
    std::vector<Bar> const& bars() const; // Ooops, impossible to move to a `deque` 
             // or to enable polymorphic behavior 
private: 
    std::vector<Bar> mBars; 
}; 

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

याद रखें: लोगों को अपने निजीकरण को उजागर करने के लिए जेल भेजा गया है!

0

आपके मामले में, Game और InputManager ऑब्जेक्ट्स सिंगलेट्स प्रतीत होते हैं। यदि ऐसा है, तो आपको केवल आश्वस्त करने की आवश्यकता है कि गेम का केवल एक उदाहरण (केवल एक इनपुट प्रबंधक) मौजूद है, और कॉन्स सजावट छोड़ें। जैसा ऊपर बताया गया है, इस मामले में, मैं निहित वस्तुओं, कोई पॉइंटर्स का संदर्भ वापस कर दूंगा।

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