2011-02-10 15 views
15
class Foo 
{ 
    int Bar; 

    public: 

    int& GetBar() const 
    { 
     return Bar; 
    } 
} 

क्या यह ठीक है कि GetBar एक const विधि है? यह वास्तव में कुछ भी नहीं बदल रहा है, लेकिन यह इसे बदलने के साधनों के साथ "बाहरी दुनिया" प्रदान कर रहा है।कॉन्स्टेंस विधियां जो संदर्भ संदर्भ

+0

मुझे लगता है कि आप पहले से ही अपने प्रश्न का उत्तर दे चुके हैं। इसके अतिरिक्त उदाहरण में बार पहले से ही सार्वजनिक है। – XAder

+0

'और बार 'में' const int * 'टाइप किया गया है, न कि' int & '। आप संकलक आपको बता रहे हैं कि यह ठीक नहीं है। –

+0

क्या आपने संकलन करने की कोशिश की है? कंपाइलर ने आपको क्या बताया? –

उत्तर

18

आप अपने कोड लिखने में कोई गलती है, यह क्या आप शायद मतलब है:

class Foo 
{ 
    int Bar; 

    public: 

    int& GetBar() const 
    { 
     return Bar; // Removed the ampersand, because a reference is returned, not an address 
    } 
} 

और कोई, यह कानूनी नहीं है ।const के साथ एक विधि टैग करते समय, न केवल आप वादा कर रहे हैं कि आप किसी भी आंतरिक स्थिति को स्पर्श नहीं करेंगे, आप यह भी वादा करते हैं कि आप किसी भी वस्तु को वापस नहीं करेंगे जिसका उपयोग ऑब्जेक्ट की स्थिति को बदलने के लिए किया जा सकता है। GetBar() के दायरे के बाहर बार के मान को संशोधित करने के लिए एक गैर-कॉन्स्ट संदर्भ का उपयोग किया जा सकता है, इसलिए आप यह कह रहे हैं कि आप वादा नहीं कर सकते हैं।

आपको या तो गैर-कॉन्स होने के लिए विधि को बदलना होगा, एक कॉन्स्ट संदर्भ वापस करना होगा, या Barmutable के रूप में चिह्नित करके वादे से मुक्त होना चाहिए। उदा .: mutable int Bar;mutable कीवर्ड संकलक को बताता है कि वस्तु की तार्किक स्थिरता Bar की स्थिति पर निर्भर नहीं है। फिर आपको इसके साथ जो कुछ भी करने की अनुमति है उसे करने की अनुमति है।

4

नहीं, जब से तुम नहीं कर सकते निम्न असाइनमेंट: const int x; int &y = x;

आप हालांकि ऐसा const int x; const int &y = x;

और रास्ते में विधि ओवरलोडिंग और दोनों स्थिरांक और गैर स्थिरांक बनाने में कोई समस्या नहीं है है सकते हैं क्या वेरिएंट।

3

शायद आप Bar, &Bar पर वापस नहीं जाना चाहते हैं। वैसे भी, मैं Comeau में इस कोड को गिरा दिया:

class Foo 
{ 
    int Bar; 

    public: 

    int& GetBar() const 
    { 
     return &Bar; 
    } 
}; 

int main(int argc, char** argv) 
{ 
    Foo x; 
    int y = x.GetBar(); 
    y = 5; 
    return 0; 
} 

और त्रुटि मिली:

line 9: error: qualifiers dropped in binding reference of type 
      "int &" to initializer of type "const int" 
      return Bar; 
       ^
1

सबसे पहले, एक संदर्भ आप संदर्भित वस्तु पर एम्परसेंड ऑपरेटर का उपयोग करने की जरूरत नहीं लौटने के लिए ; यदि आप पॉइंटर प्राप्त करना चाहते हैं तो इसकी आवश्यकता है। तो, मुझे लगता है कि आप return Bar; लिखना चाहते थे।

फिर, नहीं, आप ऐसा नहीं कर सकते; एक const विधि में आप एक constthis सूचक है (आपके मामले में यह एक const Foo * होगा), जिसका अर्थ है कि किसी भी संदर्भ आप अपने क्षेत्रों को प्राप्त कर सकते हैं एक const संदर्भ हो जाएगा, के बाद से आप उन्हें एक के माध्यम से एक्सेस कर रहे हैं " const पथ "।

इस प्रकार, यदि आप उस कोड में जो किया है उसे करने का प्रयास करते हैं तो आपको एक संकलन त्रुटि मिल जाएगी, क्योंकि आप const int & के साथ int & (आपकी विधि का वापसी मूल्य) प्रारंभ करने का प्रयास करेंगे (संदर्भ Bar से प्राप्त करें), जो स्पष्ट रूप से वर्जित है।

जी ++ वास्तव में कहते हैं:

testconstref.cpp: In member function ‘int& Foo::GetBar() const’: 
testconstref.cpp:9: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘const int*’ 

जो है मैं तो बस क्या कहा। :)

यदि, इसके बजाय, आप constconst विधि से किसी क्लास फ़ील्ड के संदर्भ में const संदर्भ वापस लेते हैं तो आपको कोई समस्या नहीं होगी।


  1. को छोड़कर खेतों mutable के रूप में चिह्नित है, जो संकलक कि ऐसे क्षेत्रों भी const तरीकों से परिवर्तनीय हैं करने के लिए कहता है; इस अपवाद को const ऑब्जेक्ट की "वास्तविक" स्थिति को बदलने के तरीकों में मामलों को बदलने की अनुमति देने के लिए पेश किया गया है जब यह "तार्किक" स्थिति को परिवर्तित नहीं करता है; इस आलसी मूल्यांकन, संदर्भ गिनती, लागू करने के लिए उपयोगी हो सकता है ...
0

const किसी सदस्य फ़ंक्शन में संशोधक ऑब्जेक्ट के राज्य को इसके दायरे में बदलने की अनुमति नहीं देता है। कंपाइलर बस जांचता है कि यह फ़ंक्शन ऑब्जेक्ट की स्थिति को संशोधित कर रहा है या नहीं, इसके दायरे में। एक और उदाहरण लेना -

class foo 
{ 
    int num ; 
    public : 
     foo(int anum) 
     { 
      anum = 10; 
     } 
     int getNum() 
     { 
      return num; 
     } 
}; 

foo obj; 
int& myNum = obj.getNum() ; // myNum is just an alias to the private class variable num 
myNum = 40; // Actually changes the content of the private variable. 

तो, संकलक बस पहुँच विनिर्देशक की जाँच करता है (यानी, कि क्या यह चर सुलभ या इस दायरे में नहीं है), लेकिन नहीं निजी/सार्वजनिक/संरक्षित चर की स्मृति स्थान के बारे में अगर कुछ अन्य चर के लिए लौट आए ।

1

जब आप किसी कॉन्स्ट विधि में हों तो आपकी कक्षा के सदस्यों को कॉन्स्ट माना जाता है। इसलिए Barint आपकी कक्षा के भीतर है और const intGetBar() const के संदर्भ में यह "const int" है। इसलिए एक गैर स्थिरांक संदर्भ या सूचक के रूप में यह लौट कर के रूप में बस के रूप में गैर-कानूनी है:

const int y = 57; int& z = y;

इस y में स्थिरांक-शुद्धता भले ही 2 लाइन वास्तव में (अभी तक) कुछ भी नहीं बदला है टूट जाता है।

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

इस प्रकार इस कानूनी होगा (अक्सर "उथले" constness कहा जाता है):

class A 
{ 
    Foo * foo; 

    public: 
    Foo * getFoo() const // legal. does not have to return const Foo * 
    { 
     return foo; 
    } 
}; 

ध्यान रखें कि आपके मूल कोड में आप गैर स्थिरांक संदर्भ द्वारा Bar वापस जाने के लिए अगर यह mutable थे की अनुमति दी जाएगी, क्योंकि वे सदस्य सदस्य कार्यों की स्थिरता से बंधे नहीं हैं।

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