'कॉन्स्ट' का अर्थ एक वर्ग की घोषणा में अंतिम है?


727

constइन जैसी घोषणाओं का क्या अर्थ है ? constमुझे confuses।

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

जवाबों:


951

जब आप constकीवर्ड को एक विधि में जोड़ते हैं तो thisपॉइंटर अनिवार्य रूप से constऑब्जेक्ट के लिए पॉइंटर बन जाएगा , और इसलिए आप किसी भी सदस्य डेटा को बदल नहीं सकते हैं। (जब तक आप उपयोग नहीं करते हैं mutable, उस पर और बाद में)।

constकीवर्ड कार्यों हस्ताक्षर जिसका अर्थ है कि आप इसी तरह के दो तरीकों, जिनमें जब वस्तु है कहा जाता है लागू कर सकते हैं का हिस्सा है const, और एक है कि नहीं है।

#include <iostream>

class MyClass
{
private:
    int counter;
public:
    void Foo()
    { 
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        std::cout << "Foo const" << std::endl;
    }

};

int main()
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
}

यह आउटपुट करेगा

Foo
Foo const

नॉन-कास्ट विधि में आप उदाहरण के सदस्यों को बदल सकते हैं, जो आप constसंस्करण में नहीं कर सकते । यदि आप उपरोक्त उदाहरण में विधि घोषणा को कोड में बदलते हैं, तो आपको कुछ त्रुटियां मिलेंगी।

    void Foo()
    {
        counter++; //this works
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++; //this will not compile
        std::cout << "Foo const" << std::endl;
    }

यह पूरी तरह से सच नहीं है, क्योंकि आप एक सदस्य को चिह्नित कर सकते हैं mutableऔर एक constविधि फिर इसे बदल सकती है। यह ज्यादातर आंतरिक काउंटर और सामान के लिए उपयोग किया जाता है। उस के लिए समाधान नीचे कोड होगा।

#include <iostream>

class MyClass
{
private:
    mutable int counter;
public:

    MyClass() : counter(0) {}

    void Foo()
    {
        counter++;
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++;    // This works because counter is `mutable`
        std::cout << "Foo const" << std::endl;
    }

    int GetInvocations() const
    {
        return counter;
    }
};

int main(void)
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
    std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}

जो उत्पादन होगा

Foo
Foo const
Foo has been invoked 2 times

187

कास्ट का मतलब है कि विधि वर्ग के किसी भी सदस्य को बदलने का वादा नहीं करती है। आप ऑब्जेक्ट के सदस्यों को निष्पादित करने में सक्षम होंगे जो कि इतने चिह्नित हैं, भले ही वह वस्तु स्वयं चिह्नित हो const:

const foobar fb;
fb.foo();

कानूनी होगा।

देखें कि C ++ में "const" के कितने और कौन से उपयोग हैं? अधिक जानकारी के लिए।


47

constक्वालीफायर साधन तरीकों में से किसी भी मूल्य पर कहा जा सकता है कि foobar। अंतर तब आता है जब आप एक कांस्टेबल ऑब्जेक्ट पर एक गैर-कॉन्स्टेंस विधि को कॉल करने पर विचार करते हैं। विचार करें कि क्या आपके foobarप्रकार में निम्नलिखित अतिरिक्त विधि घोषणा थी:

class foobar {
  ...
  const char* bar();
}

विधि bar()गैर-कास्ट है और इसे केवल गैर-कॉस्ट मानों से एक्सेस किया जा सकता है।

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

constहालाँकि इसके पीछे का विचार उन तरीकों को चिह्नित करना है जो कक्षा की आंतरिक स्थिति को नहीं बदलेंगे। यह एक शक्तिशाली अवधारणा है लेकिन वास्तव में C ++ में लागू नहीं है। यह एक गारंटी से अधिक एक वादा है। और एक जो अक्सर टूट जाता है और आसानी से टूट जाता है।

foobar& fbNonConst = const_cast<foobar&>(fb1);

3
मैंने सोचा था कि उत्तर अन्य कास्ट तरीकों के बारे में है न कि कॉस्ट ऑब्जेक्ट्स के बारे में।
मायकोला गोलूबेव

"विचार के पीछे constयद्यपि उन तरीकों को चिह्नित करना है जो वर्ग की आंतरिक स्थिति को बदल नहीं देंगे " के लिए धन्यवाद । यह वास्तव में मैं क्या देख रहा था।
कोवैक

1
@JaredPar का मतलब यह है कि किसी भी सदस्य को रीड-ओनली ऑपरेशन का प्रतिनिधित्व करने वाले फ़ंक्शन के रूप में चिह्नित किया जाना चाहिए const?
कोवैक

26

इन कॉन्स्ट का मतलब है कि कंपाइलर एरर होगा अगर 'कॉन्स्ट के साथ' मेथड आंतरिक डेटा को बदल देता है।

class A
{
public:
    A():member_()
    {
    }

    int hashGetter() const
    {
        state_ = 1;
        return member_;
    }
    int goodGetter() const
    {
        return member_;
    }
    int getter() const
    {
        //member_ = 2; // error
        return member_;
    }
    int badGetter()
    {
        return member_;
    }
private:
    mutable int state_;
    int member_;
};

कसौटी

int main()
{
    const A a1;
    a1.badGetter(); // doesn't work
    a1.goodGetter(); // works
    a1.hashGetter(); // works

    A a2;
    a2.badGetter(); // works
    a2.goodGetter(); // works
    a2.hashGetter(); // works
}

अधिक जानकारी के लिए इसे पढ़ें


1
पर एक सवाल constसदस्य कार्यों कि उल्लेख नहीं है परिवर्तनशील सबसे अच्छे रूप में अधूरा है।
IInspectable

13

ब्लेयर का जवाब निशान पर है।

हालांकि ध्यान दें कि एक mutableक्वालीफायर है जो एक वर्ग के डेटा सदस्यों में जोड़ा जा सकता है। चिह्नित किए गए किसी भी सदस्य को अनुबंध का उल्लंघन किए बिना एक विधि में संशोधित किया जा सकता है ।constconst

आप इसका उपयोग कर सकते हैं (उदाहरण के लिए) यदि आप किसी ऑब्जेक्ट को यह याद रखना चाहते हैं कि किसी विशेष विधि को कितनी बार कहा जाता है, तो उस पद्धति के "तार्किक" कब्ज को प्रभावित नहीं करता है।


10

C ++ सामान्य ज्ञान में एक कॉन्स्टेबल मेंबर फंक्शन का अर्थ : आवश्यक इंटरमीडिएट प्रोग्रामिंग स्पष्ट विवरण देता है:

एक कक्षा X के गैर-सदस्य सदस्य फ़ंक्शन में इस सूचक का प्रकार X * const है। यही है, यह एक गैर-स्थिर एक्स के लिए एक निरंतर सूचक है (कॉन्स्ट पॉइंटर्स और पॉइंटर्स टू कॉन्स्ट [7, 21] देखें)। क्योंकि जिस वस्तु को यह संदर्भित करता है वह कब्ज नहीं है, इसे संशोधित किया जा सकता है। एक कक्षा X के एक सदस्य सदस्य कार्य में इसका प्रकार है const X * const। यही कारण है कि, यह एक स्थिर X के लिए एक निरंतर सूचक है। क्योंकि जिस वस्तु को यह संदर्भित करता है वह कास्ट है, इसे संशोधित नहीं किया जा सकता है। यह कांस्ट और नॉन-कास्ट सदस्य कार्यों के बीच अंतर है।

तो आपके कोड में:

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

आप इसे इस रूप में सोच सकते हैं:

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};

thisनहीं है const। इसे संशोधित नहीं किया जा सकता है, इसका कारण यह है कि यह एक प्रचलन है।
ब्रायन

7

जब आप constविधि हस्ताक्षर में उपयोग करते हैं (जैसे आपके कहा const char* foo() const;:) आप संकलक को बता रहे हैं कि जिस मेमोरी को इंगित thisकिया गया है उसे इस विधि (जो fooयहां है) द्वारा नहीं बदला जा सकता है ।


6

मैं निम्नलिखित बिंदु जोड़ना चाहूंगा।

आप यह भी कर सकते हैं यह एक const &औरconst &&

इसलिए,

struct s{
    void val1() const {
     // *this is const here. Hence this function cannot modify any member of *this
    }
    void val2() const & {
    // *this is const& here
    }
    void val3() const && {
    // The object calling this function should be const rvalue only.
    }
    void val4() && {
    // The object calling this function should be rvalue reference only.
    }

};

int main(){
  s a;
  a.val1(); //okay
  a.val2(); //okay
  // a.val3() not okay, a is not rvalue will be okay if called like
  std::move(a).val3(); // okay, move makes it a rvalue
}

बेझिझक जवाब में सुधार करें। मैं कोई विशेषज्ञ नहीं हूं


1
*thisसदैव एक अंतराल होता है, भले ही सदस्य कार्य rvalue-ref-योग्य हो और उसे एक अंतराल पर कहा जाता है। उदाहरण है
होलीब्लैककैट

1
हां, तो मुझे अपने वर्तमान उत्तर को कैसे सुधारना चाहिए?
कोडर 3101

मेरा मतलब है कि ब्लॉक में टिप्पणी में क्या लिखना है, जो व्यवहार को सही ठहराता है
1919 कोडर 3101

अपडेट किया गया। क्या ये ठीक है?
कोडर 3101

2

फंक्शन डिक्लेरेशन के साथ उपयोग किया जाने वाला कांस्ट कीवर्ड यह निर्दिष्ट करता है कि यह एक कास्ट मेंबर फंक्शन है और यह ऑब्जेक्ट के डेटा सदस्यों को बदलने में सक्षम नहीं होगा ।


1

https://isocpp.org/wiki/faq/const-correctness#const-member-fns

" constसदस्य फ़ंक्शन" क्या है ?

एक सदस्य फ़ंक्शन जो अपनी वस्तु का निरीक्षण करता है (म्यूटेट्स के बजाय)।

सदस्य फ़ंक्शन के पैरामीटर सूची के ठीक बाद एक constसदस्य फ़ंक्शन को एक constप्रत्यय द्वारा दर्शाया जाता है । constप्रत्यय वाले सदस्य कार्यों को "कांस्टेबल सदस्य कार्य" या "निरीक्षक" कहा जाता है। बिना constप्रत्यय के सदस्य कार्यों को "गैर-कास्ट सदस्य कार्य" या "म्यूटेटर" कहा जाता है।

class Fred {
public:
  void inspect() const;   // This member promises NOT to change *this
  void mutate();          // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
  changeable.inspect();   // Okay: doesn't change a changeable object
  changeable.mutate();    // Okay: changes a changeable object
  unchangeable.inspect(); // Okay: doesn't change an unchangeable object
  unchangeable.mutate();  // ERROR: attempt to change unchangeable object
}

कॉल करने का प्रयास unchangeable.mutate()संकलन समय पर पकड़ा गया त्रुटि है। इसके लिए कोई रनटाइम स्पेस या स्पीड पेनल्टी नहीं है const, और इसे रनटाइम पर जाँचने के लिए आपको टेस्ट-केस लिखने की आवश्यकता नहीं है।

सदस्य फ़ंक्शन constपर अनुरेखण inspect()का मतलब यह होना चाहिए कि विधि ऑब्जेक्ट के सार (क्लाइंट-दृश्यमान) स्थिति को नहीं बदलेगी । यह कहने के तरीके से थोड़ा अलग है कि विधि वस्तु की संरचना के "कच्चे बिट्स" को नहीं बदलेगी। C ++ कंपाइलरों को "बिटवाइज़" व्याख्या लेने की अनुमति नहीं दी जाती है जब तक कि वे एलियासिंग समस्या को हल नहीं कर सकते हैं, जिसे सामान्य रूप से हल नहीं किया जा सकता है (अर्थात, एक गैर-कॉन्स्टेंस उपनाम मौजूद हो सकता है जो ऑब्जेक्ट की स्थिति को संशोधित कर सकता है)। इस एलियासिंग मुद्दे से एक और (महत्वपूर्ण) अंतर्दृष्टि: एक सूचक को एक संकेत के साथ एक ऑब्जेक्ट पर इंगित करना इस बात की गारंटी नहीं देता है कि वस्तु नहीं बदलेगी; यह केवल वादा करता है कि वस्तु उस सूचक के माध्यम से नहीं बदलेगी ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.