2008-10-02 14 views
15

उदाहरण के लिए, मैं एक वर्ग है लगता है:सी ++ में, कंपाइलर गैर-कॉन्स्ट फ़ंक्शन का चयन क्यों करता है जब कॉन्स्ट भी काम करेगा?

Foo *a; 
// Do stuff... 
std::string name = a->Name(); // <-- chooses the non-const version 

क्या किसी को पता है कि क्यों संकलक गैर स्थिरांक का चयन करेंगे:

class Foo 
{ 
public: 
    std::string& Name() 
    { 
     m_maybe_modified = true; 
     return m_name; 
    } 

    const std::string& Name() const 
    { 
     return m_name; 
    } 
protected: 
    std::string m_name; 
    bool m_maybe_modified; 
}; 

और कहीं और कोड में, मैं इस तरह कुछ है इस मामले में संस्करण?

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

+0

यदि आप किसी कॉन्स्ट फ़ंक्शन में कुछ चर बदलना चाहते हैं, तो आपसी विशेषता का उपयोग करें। – ypnos

+0

आपका मतलब है "mutable" – Lev

+0

... और "सदस्य चर", मुझे लगता है। – Niklas

उत्तर

14

दो जवाब दिमाग में वसंत:

  1. गैर स्थिरांक संस्करण एक करीब मुकाबला नहीं है।

  2. यदि इसे गैर-कॉन्स केस के लिए कॉन्स्ट अधिभार कहा जाता है, तो यह किस स्थिति में कभी गैर-कॉन्स्ट अधिभार को कॉल करेगा?

आप इसे एक const Foo * को a कास्टिंग द्वारा अन्य अधिभार उपयोग करने के लिए मिल सकता है।

संपादित करें:C++ Annotations से

इससे पहले, खंड 2.5.11 अवधारणा समारोह से अधिक भार के पेश किया गया था में। वहां ध्यान दिया गया कि सदस्य फ़ंक्शंस केवल द्वारा उनके कॉन्स विशेषता द्वारा अधिभारित किया जा सकता है। उन मामलों में, संकलक सदस्य समारोह मिलान सबसे निकट वस्तु का स्थिरांक-योग्यता का उपयोग करेगा:

+0

"एनोसिएशन" -> "एनोटेशन" –

+0

दोह। धन्यवाद, तय है। –

16

क्योंकि एक एक स्थिरांक सूचक नहीं है। इसलिए, एक गैर-कॉन्स फ़ंक्शन एक करीबी मैच है। यहाँ कैसे आप स्थिरांक फ़ंक्शन को कॉल कर सकते हैं: तुम दोनों एक स्थिरांक और एक गैर स्थिरांक अधिभार है, तो

const Foo* b = a; 
std::string name = b->Name(); 

, और एक गैर स्थिरांक वस्तु पर स्थिरांक एक कॉल करना चाहते हैं, इस बात का संकेत हो सकता है खराब डिजाइन

+0

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

+0

कॉन्स्ट ओवरलोड को एक अलग नाम देने के बारे में कैसे? या दोनों एक कॉन्स अधिभार और एक अलग नामित समारोह, एक दूसरे को ऑनलाइन कॉल कर रहे हैं? – Lev

+0

बस लेने के लिए एक नाइट ... सूचक नहीं है ... यह आपके उदाहरण में "कॉन्स्टेंट करने के लिए सूचक" है। –

5

कंपाइलर इस बात को ध्यान में रखता है कि आप अपने निर्धारण में वापसी मूल्य का उपयोग कैसे कर रहे हैं; यह नियमों का हिस्सा नहीं है। यदि आप

std::string name = b->Name(); 

या

b->Name() = "me"; 

यह संस्करण है कि दोनों ही मामलों में काम करता है चुनने के लिए कर रहे हैं यह पता नहीं है।

+0

सही उत्तर +1 –

+0

प्रश्न वापसी मूल्य की स्थिरता या नहीं के बारे में नहीं था, यह वस्तु की स्थिरता के बारे में था। -1 हालांकि मैं नहीं था। –

+0

मैं संकलक के लिए संभावित समस्याओं को समझता हूं, लेकिन मुझे लगता है कि यह उदाहरण में जैसे कुछ सरल चेक करने में सक्षम होगा, जहां यह तुरंत एक प्रतिलिपि के लिए वापसी का उपयोग करेगा और फिर इसे छोड़ देगा। –

0

आप "नाम() कॉन्स्ट" के बराबर "cName" फ़ंक्शन जोड़ सकते हैं। इस तरह आप पहले कॉन्स्ट ऑब्जेक्ट को कास्ट किए बिना फ़ंक्शन के कॉन्स्ट वर्जन को कॉल कर सकते हैं।

यह सी ++ 0x में नए कीवर्ड ऑटो के साथ अधिकतर उपयोगी है, यही कारण है कि वे पुस्तकालय को अद्यतन कर रहे हैं ताकि cbegin(), cend(), crbegin(), crend ​​() को const_iterator को वापस लौटाया जा सके, भले ही वस्तु गैर-आधार है।

आप जो कर रहे हैं वह शायद सेटनाम() फ़ंक्शन होने से बेहतर होता है जो आपको अंतर्निहित कंटेनर के संदर्भ को वापस करने के बजाय नाम बदलने की अनुमति देता है और फिर "शायद" इसे संशोधित किया जाता है।

+0

मुझे एहसास है कि यह एक setName() फ़ंक्शन के साथ बेहतर हो सकता है, लेकिन फिर, उदाहरण कुछ हद तक विकसित हुआ था। वास्तविकता में, हमारे पास पॉइंटर्स ऑब्जेक्ट्स होते हैं जिसमें अन्य ऑब्जेक्ट होते हैं, और जहां संभव हो, कॉन्स्ट पॉइंटर्स को वापस लौटाया जाएगा, जब "int c = a-> बी() -> GetC();", आदि –

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

  • कोई संबंधित समस्या नहीं^_^