2008-09-08 18 views
8

इस तरह की घोषणा को देखते हुए:सी ++ में किसी विधि के साथ उपयोग किए जाने पर कॉन्स्ट ऑपरेटर का क्या अर्थ है?

class A { 
public: 
    void Foo() const; 
}; 

इसका क्या अर्थ है?

Google इसे चालू करता है:

सदस्य फ़ंक्शंस को उनके बाद कॉन्स कीवर्ड के साथ घोषित किया जाना चाहिए यदि वे किसी कॉन्स (इस) ऑब्जेक्ट पर काम कर सकते हैं। यदि फ़ंक्शन घोषित नहीं किया गया है, तो किसी कॉन्स ऑब्जेक्ट पर लागू नहीं किया जा सकता है, और संकलक एक त्रुटि संदेश देगा।

लेकिन मुझे लगता है कि कुछ उलझन में है; क्या कोई इसे बेहतर शर्तों में रख सकता है?

धन्यवाद।

उत्तर

12

अपनी कक्षा A की एक भिन्नता पर विचार करें।

class A { 
public: 
    void Foo() const; 
    void Moo(); 

private: 
    int m_nState; // Could add mutable keyword if desired 
    int GetState() const { return m_nState; } 
    void SetState(int val) { m_nState = val; } 
}; 

const A *A1 = new A(); 
A *A2 = new A(); 

A1->Foo(); // OK 
A2->Foo(); // OK 

A1->Moo(); // Error - Not allowed to call non-const function on const object instance 
A2->Moo(); // OK 

एक समारोह घोषणा पर const कीवर्ड संकलक कि समारोह A की स्थिति संशोधित करने के लिए नहीं किसी अनुबंध के लिए बाध्य है करने के लिए इंगित करता है। इस प्रकार आप A::Foo के भीतर गैर-const फ़ंक्शंस को कॉल करने में असमर्थ हैं और न ही सदस्य चर के मान को बदल सकते हैं।

समझाने के लिए, फू()A::SetState आह्वान नहीं हो सकता है के रूप में यह गैर घोषित किया जाता है const, A::GetState लेकिन ठीक है क्योंकि यह स्पष्ट रूप से const घोषित किया जाता है। m_nState सदस्य को तब तक बदला नहीं जा सकता है जब तक कि कीवर्ड mutable कीवर्ड के साथ घोषित न किया जाए।

const के इस उपयोग का एक उदाहरण सदस्य चर के मान प्राप्त करने के लिए 'गेटटर' फ़ंक्शंस के लिए है।

@ 1800 सूचना: मैं mutable के बारे में भूल गया!

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

+0

महान उत्तर - वास्तव में स्पष्ट और संक्षेप में। मेरा +1 मिला –

1

कि कारण होगा विधि नहीं करने के लिए वस्तु const क्वालीफायर के साथ

3

कार्य किसी भी सदस्य चर को संशोधित करने की अनुमति नहीं है के किसी भी सदस्य चर को बदलने में सक्षम हो। उदाहरण के लिए:

const A obj = new A(); 

जब एक वस्तु स्थिरांक है, केवल सदस्य कार्यों कि उस वस्तु पर कहा जा सकता है कार्यों स्थिरांक घोषित किया जाता है:

class A 
{ 
    int x; 
    mutable int y; 

    void f() const 
    { 
     x = 1; // error 
     y = 1; // ok because y is mutable 
    } 
}; 
2

सी ++ वस्तुओं स्थिरांक घोषित किया जा सकता है। ऑब्जेक्ट कॉन्स को ऑब्जेक्ट को पढ़ने के रूप में व्याख्या किया जा सकता है। एक कॉन्स ऑब्जेक्ट को बदला नहीं जा सकता है, यानी ऑब्जेक्ट का कोई डेटा सदस्य बदला जा सकता है। सदस्य फ़ंक्शन कॉन्स्ट को घोषित करने का अर्थ है कि फ़ंक्शन को ऑब्जेक्ट के डेटा सदस्यों में कोई भी परिवर्तन करने की अनुमति नहीं है।

+0

एर ... कॉन्स ए * ओबीजे = नया ए(); ... आप "स्टार" भूल गए ... :-) – paercebal

5

यह एक उत्तर नहीं है, सिर्फ एक पक्ष टिप्पणी है। यह अत्यधिक जितना संभव हो वैरिएबल और स्थिरांक const घोषित करने की अनुशंसा की जाती है।

  1. यह आपके वर्ग के उपयोगकर्ताओं (यहां तक ​​कि विशेष रूप से स्वयं) के लिए आपके इरादे को संचारित करता है।
  2. कंपाइलर आपको उन इरादों के प्रति ईमानदार बनाए रखेगा। - यानी, यह कंपाइलर चेक दस्तावेज की तरह है।
  3. परिभाषा के अनुसार, यह उन राज्य परिवर्तनों को रोकता है जिन्हें आप उम्मीद नहीं कर रहे थे और संभवतः, आपको अपनी विधियों के दौरान उचित धारणाएं करने की अनुमति दे सकते हैं।
  4. const आपके कोड के माध्यम से प्रचार करने का एक मजेदार तरीका है। इस प्रकार, const का उपयोग जल्दी और जितनी बार संभव हो सके शुरू करना वाकई अच्छा विचार है। const शुरू करने का निर्णय लेने से गेम में देर से आपका कोड दर्दनाक (आसान, लेकिन परेशान) हो सकता है।

यदि आप स्थैतिक, संकलित समय जांच के साथ एक भाषा का उपयोग कर रहे हैं तो यह संभव है कि जितना संभव हो उतना उपयोग करना एक अच्छा विचार है ... यह वास्तव में एक और प्रकार का परीक्षण है। अनुभव से

2

दो सर्वोत्तम प्रथाओं का सुझाव दिया:

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

(2) व्यावहारिक होने पर परिवर्तनीय चर से बचें। एक आकर्षक जाल राज्य को बदलने के लिए पढ़ने के संचालन की अनुमति देने के लिए हो सकता है, जैसे कि यदि आप "स्मार्ट" ऑब्जेक्ट बना रहे हैं जो आलसी या एसिंक्रोनस i/o संचालन करता है। यदि आप इसे केवल एक छोटे से परिवर्तनीय चर (जैसे बूल) के साथ प्रबंधित कर सकते हैं, तो, मेरे अनुभव में, यह समझ में आता है। हालांकि, अगर आप कुछ ऑपरेशंस वैरिएबल को कुछ ऑपरेशंस कॉन्स रखने के लिए म्यूटेबल के रूप में चिह्नित करते हैं, तो आप कॉन्स कीवर्ड के उद्देश्य को हरा रहे हैं। क्या गलत हो सकता है कि एक ऐसा फ़ंक्शन जो सोचता है कि यह आपकी कक्षा में बदलाव नहीं कर रहा है (क्योंकि यह केवल कॉन्स्ट विधियों को कॉल करता है), मैंने आपके कोड में एक बग का आह्वान किया है, और यह भी समझने में बहुत प्रयास कर सकता है कि यह बग आपकी कक्षा में है, क्योंकि अन्य कोडर (सही) मानते हैं कि आपका डेटा स्थिर है क्योंकि वह केवल कॉन्स्ट विधियों को बुला रहा है।

2

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

इसके अतिरिक्त, यदि आसानी से होनी चाहिए तो आप आसानी से समस्याओं में भाग लेंगे! यह कोड के माध्यम से भी रेंग देगा, और इसे और भी बदतर बना देगा।

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