2010-01-28 16 views
17

मैंने कक्षाओं में कार्यों के बाद रखे गए कॉन्स कीवर्ड के बहुत सारे उपयोग देखे हैं, इसलिए मैं जानना चाहता था कि इसके बारे में क्या था। मैंने यहां smth पढ़ा: http://duramecho.com/ComputerInformation/WhyHowCppConst.htmlकक्षा के कार्यों में 'कॉन्स्ट' का उपयोग

यह कहता है कि कॉन्स का उपयोग किया जाता है क्योंकि फ़ंक्शन "ऑब्जेक्ट में किसी भी सदस्य चर को बदलने का प्रयास कर सकता है"। यदि यह सत्य है, तो इसे हर जगह इस्तेमाल किया जाना चाहिए, क्योंकि मैं नहीं चाहता कि किसी भी सदस्य चर को किसी भी तरह से बदला या बदला जाए।

class Class2 
{ void Method1() const; 
    int MemberVariable1;} 

तो, वास्तविक परिभाषा और कॉन्स्ट का उपयोग क्या है?

+3

यदि आपके सदस्य चर कभी नहीं बदलते हैं, तो आपके पास सदस्य चर क्यों हैं? –

+6

क्योंकि वह एक कक्षा चाहता है जो अपरिवर्तनीय है? यह अनुचित नहीं है। –

+1

मैं वास्तव में एक सी ++ व्यक्ति नहीं हूं, इसलिए यह "गॉचा" प्रश्न से अधिक ब्याज का सवाल था। यदि आप वास्तव में अपरिवर्तनीय होना चाहते हैं तो आप अपने सभी सदस्यों को "कॉन्स्ट" क्यों घोषित नहीं करेंगे? या आप दोनों सदस्यों को कॉन्स और विधियों के रूप में घोषित करेंगे? –

उत्तर

29

एक स्थिरांक विधि एक स्थिरांक वस्तु पर कहा जा सकता है:

class CL2 
{ 
public: 
    void const_method() const; 
    void method(); 

private: 
    int x; 
}; 


const CL2 co; 
CL2 o; 

co.const_method(); // legal 
co.method();  // illegal, can't call regular method on const object 
o.const_method(); // legal, can call const method on a regulard object 
o.method();   // legal 

इसके अलावा, यह भी संकलक कि स्थिरांक विधि वस्तु की स्थिति में बदलाव नहीं किया जाना चाहिए और उन समस्याओं पकड़ेगा बताता है:

void CL2::const_method() const 
{ 
    x = 3; // illegal, can't modify a member in a const object 
} 

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

+0

क्या सुरक्षा के लिए, उन सभी विधियों के लिए आपूर्ति करना चाहिए जिन्हें ऑब्जेक्ट की स्थिति बदलने की उम्मीद नहीं है? (उदाहरण के लिए, गेटर्स) – gen

+0

कॉन्स शुद्धता के लिए, हाँ। – U007D

1

यदि यह सत्य है, तो इसे हर जगह इस्तेमाल किया जाना चाहिए, क्योंकि मैं नहीं चाहता कि किसी भी सदस्य चर को किसी भी तरह से बदला या बदला जाए?

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

2

इसका अर्थ यह है कि आप एक कॉन्स्ट फ़ंक्शन सदस्य को कॉल करने वाले ग्राहकों को गारंटी देते हैं कि ऑब्जेक्ट की स्थिति बदलेगी नहीं। तो जब आप कहते हैं कि एक सदस्य फ़ंक्शन है तो इसका मतलब है कि आप फंक्शन कॉल के दौरान किसी भी ऑब्जेक्ट सदस्य चर को नहीं बदलते हैं।

+0

यह बिल्कुल सही नहीं है - अवलोकन करने योग्य व्यवहार नहीं बदलता है, लेकिन सदस्य डेटा को 'mutable' चिह्नित किया जा सकता है। यह उदाहरण के लिए, एक बार गणना के परिणाम कैशिंग की अनुमति देता है। –

+0

यह और भी बदतर है। यदि आपके पास कुछ डेटा इंगित करने वाला सूचक है, तो सदस्य फ़ंक्शन के पीछे 'const' केवल गारंटी देता है कि सूचक नहीं बदला गया है, न कि डेटा जो इंगित करता है। अक्सर, हालांकि, डेटा को वस्तु के राज्य का हिस्सा माना जाता है। तो, वास्तव में, वह 'const' केवल सदस्य कार्य को ऑब्जेक्ट के सदस्य डेटा को बदलने से रोकता है, न कि उसके सभी राज्य। यह तात्कालिक दृढ़ता को लागू करता है, तार्किक स्थिरता नहीं। – sbi

+0

दरअसल, यह केवल बिटवाईड स्थिरता को लागू करता है, और जब आप सदस्य को परिवर्तनीय सेट करते हैं तो सभी शर्त बंद हो जाती हैं। यह वास्तव में संकलक के लिए एक संकेत है, श्री Klatchko ऊपर एक बेहतर व्याख्या है। – mikelong

2

यह कोई असामान्य नहीं है कि कोई भी सदस्य चर बदलना न पड़े, लेकिन यदि आपकी कक्षा की आवश्यकता है, तो आपको अपने सभी सदस्यों के कार्यों को बनाना चाहिए।

class A { 
    private: 
    int val; 
    public: 
    A() : val(0) {} 
    void Inc() { val++; } 
    int GetVal() const { return val; }; 
}; 

अब अगर मैं एक के दो उदाहरण बना:

A a1; 
const A a2; 

मैं कह सकता हूँ:

a1.GetVal(); 
a2.GetVal(); 

हालांकि, आप शायद कम से कम कुछ सदस्यों बदलाव करना चाहते हैं

लेकिन मैं केवल इतना कह सकता हूं:

a1.Inc(); 

एक निरंतर वस्तु का मान बदलने के लिए कोशिश कर रहा है:

a2.Inc(); 

एक संकलन त्रुटि देता है।

+0

घोषणात्मक प्रोग्रामिंग में बाहरी राज्य को बदलने का तरीका अधिक आम है - फिलहाल सी ++ में करने की सबसे आसान बात नहीं है। लेकिन अधिक धाराप्रवाह सी ++ लाइब्रेरी डिज़ाइन रास्ते पर हैं (उदाहरण के लिए [रेंज वी 3] (https://github.com/ericniebler/range-v3)) जो भविष्य में इसे और अधिक व्यावहारिक बना देगा। – U007D

1

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

3

कॉन्स, एक गैर स्थैतिक वर्ग विधि से जुड़ा हुआ, कंपाइलर को बताता है कि आपका फ़ंक्शन ऑब्जेक्ट की आंतरिक स्थिति को संशोधित नहीं करता है।

यह दो मायनों में उपयोगी है:

  • आप कोड है कि आपके स्थिरांक विधि में आंतरिक स्थिति में परिवर्तन लिख सकता हूँ, तो संकलक त्रुटि पकड़ता, रन-टाइम से एक प्रोग्रामिंग त्रुटि चलती संकलन समय के लिए।
  • यदि ग्राहक कोड निरंतर सूचक पर एक गैर-कॉन्स्ट विधि को कॉल करता है, तो संकलक त्रुटि को पकड़ता है, "चीजों को बदलने की श्रृंखला" को बनाए रखने के लिए सुनिश्चित किया जाता है।

आमतौर पर आप सभी गैर-उत्परिवर्तनीय गैर स्थैतिक वर्ग विधियों को कॉन्स्ट के रूप में घोषित करना चाहते हैं। यह पॉइंटर्स पर कॉन्स्ट क्वालीफायर का उपयोग करने के लिए कोड को कॉल करने की अनुमति देता है, और यह गलतियों को पकड़ने में मदद करता है।

विशिष्ट सी ++: आप एक क्लास सदस्य चर "mutable" घोषित कर सकते हैं और उसके बाद को को किसी कॉन्स्ट विधि से बदल सकते हैं।

3

दूसरों ने कॉन्स सदस्य कार्यों के बारे में आपके प्रश्न के तकनीकी पक्ष का उत्तर दिया है, लेकिन यहां एक बड़ी तस्वीर है - और यह const correctness का विचार है।

लंबी कहानी छोटी, स्थिरता आपके कोड के अर्थशास्त्र को स्पष्ट और लागू करने के बारे में है। एक साधारण उदाहरण लें। इस समारोह घोषणा को देखो:

bool DoTheThing(char* message); 

मान लीजिए किसी और इस समारोह में लिखा था और आप इसे कॉल करने के लिए की जरूरत है। क्या आप जानते हैं कि DoTheThing() आपके चार बफर में क्या करता है? हो सकता है कि यह सिर्फ एक फ़ाइल को संदेश लॉग करता है, या शायद यह स्ट्रिंग को बदल देता है। आप यह नहीं बता सकते कि कॉल की अर्थशास्त्र केवल फ़ंक्शन घोषणा को देखकर क्या है। यदि फ़ंक्शन स्ट्रिंग को संशोधित नहीं करता है, तो घोषणा गलत है।

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

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(msg.c_str()); 
} 

ऊपर कोड संकलन नहीं करेगा क्योंकि msg.c_str() रिटर्न एक const char*। ,

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(const_cast<char*>(msg.c_str())); 
} 

न जिनमें से यकीनन, 'बेहतर' की तुलना में कर रहे हैं:

void MyFunction() 
{ 
    std::string msg = "Hello, const correctness"; 
    DoTheThing(msg.begin()); 
} 

... या और भी बदतर: आदेश संकलित करने के लिए इस कोड को पाने के लिए, अगर आप इस तरह कुछ करने के लिए होता है मूल कोड लेकिन क्योंकि DoTheThing() एक कॉन्स्ट-गलत तरीके से लिखा गया था, तो आपको इसके चारों ओर अपना कोड मोड़ना होगा।

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