खोज…


वाक्य - विन्यास

  • class ClassOne {public: bool non_modifying_member_function () कॉन्स्ट {/ * ... * /}};
  • int ClassTwo :: non_modifying_member_function () const {/ * ... * /}
  • शून्य ClassTwo :: modifying_member_function () {/ * ... * /}
  • char non_param_modding_func (const ClassOne & one, const ClassTwo * दो) {/ * ... * /}
  • फ्लोट पैरामीटर_मॉडिफाइंग_फंक्शन (क्लासटू और एक, क्लासऑन * दो) {/ * ... * /}
  • छोटी कक्षा

टिप्पणियों

const शुद्धता एक बहुत ही उपयोगी समस्या निवारण उपकरण है, क्योंकि यह प्रोग्रामर को यह निर्धारित करने की अनुमति देता है कि कौन से कार्य अनजाने में कोड को संशोधित कर सकते हैं। यह अनजाने त्रुटियों को भी रोकता है, जैसे कि Const Correct Function Parameters में दिखाया गया है, ठीक से संकलित करने और किसी का ध्यान नहीं जाने से।

const शुद्धता के लिए एक वर्ग को डिजाइन करना बहुत आसान है, क्योंकि यह बाद में एक पूर्व-मौजूदा वर्ग में const शुद्धता को जोड़ना है। यदि संभव हो, किसी भी वर्ग है कि हो सकता है डिजाइन const सही इतना है कि यह है const , सही खुद को और दूसरों बाद में इसे संशोधित करने की परेशानी को बचाने के लिए।

ध्यान दें कि यह आवश्यक होने पर volatile शुद्धता पर भी लागू किया जा सकता है, साथ ही साथ const लिए भी समान नियम हैं, लेकिन इसका उपयोग बहुत कम बार किया जाता है।

Refrences:

ISO_CPP

मुझे कब्जियत पर बेच दो

C ++ ट्यूटोरियल

मूल बातें

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

इस सदस्य कार्यों देने के द्वारा किया जाता const सीवी-क्वालिफायर , और सूचक / संदर्भ मानकों बनाकर const , मामला यह है कि वे लिखने की आवश्यकता को छोड़कर।

class ConstCorrectClass {
    int x;

  public:
    int getX() const { return x; } // Function is const: Doesn't modify instance.
    void setX(int i) { x = i; }    // Not const: Modifies instance.
};

// Parameter is const: Doesn't modify parameter.
int const_correct_reader(const ConstCorrectClass& c) {
    return c.getX();
}

// Parameter isn't const: Modifies parameter.
void const_correct_writer(ConstCorrectClass& c) {
    c.setX(42);
}

const ConstCorrectClass invariant; // Instance is const: Can't be modified.
ConstCorrectClass         variant; // Instance isn't const: Can be modified.

// ...

const_correct_reader(invariant); // Good.   Calling non-modifying function on const instance.
const_correct_reader(variant);   // Good.   Calling non-modifying function on modifiable instance.

const_correct_writer(variant);   // Good.   Calling modifying function on modifiable instance.
const_correct_writer(invariant); // Error.  Calling modifying function on const instance.

कांस्ट की शुद्धता की प्रकृति के कारण, यह वर्ग के सदस्य कार्यों से शुरू होता है, और बाहर की ओर काम करता है; यदि आप किसी const इंस्टेंस से किसी नॉन- const मेंबर फंक्शन को कॉल करने की कोशिश करते हैं, या नॉन- const इंस्टेंस को const रूप में माना जाता है, तो कंपाइलर आपको cv-क्वालिफायर खोने के बारे में एक एरर देगा।

कॉस्ट करेक्ट क्लास डिजाइन

एक में const -correct वर्ग, सभी सदस्य कार्य करता है जो तार्किक राज्य में परिवर्तन नहीं करते है this सीवी-योग्य के रूप में const , यह दर्शाता है कि वे किसी भी वस्तु से अलग बदलाव न करें ( mutable जो स्वतंत्र रूप से में भी संशोधित किया जा सकता क्षेत्रों, const उदाहरणों ); यदि एक const cv- योग्य फ़ंक्शन एक संदर्भ देता है, तो वह संदर्भ भी const होना चाहिए। यह उन्हें निरंतर और गैर-सीवी-योग्य दोनों उदाहरणों पर बुलाया जा सकता है, क्योंकि एक const T* एक T* या एक const T* लिए बाध्य करने में सक्षम है। यह बदले में, फ़ंक्शंस को उनके पारित-दर-संदर्भ मापदंडों को const रूप में घोषित करने की अनुमति देता है, जब उन्हें किसी भी कार्यक्षमता को खोए बिना संशोधित करने की आवश्यकता नहीं होती है।

इसके अलावा, एक const सही वर्ग में, सभी पारित-दर-संदर्भ फ़ंक्शन पैरामीटर const सही होंगे, जैसा कि Const Correct Function Parameters में चर्चा की गई है, ताकि उन्हें केवल तभी संशोधित किया जा सके जब फ़ंक्शन स्पष्ट रूप से उन्हें संशोधित करने की आवश्यकता हो।

सबसे पहले, आइए this cv-क्वालिफायर को देखें:

// Assume class Field, with member function "void insert_value(int);".

class ConstIncorrect {
    Field fld;

  public:
    ConstIncorrect(Field& f); // Modifies.

    Field& getField();        // Might modify.  Also exposes member as non-const reference,
                              //  allowing indirect modification.
    void setField(Field& f);  // Modifies.

    void doSomething(int i);  // Might modify.
    void doNothing();         // Might modify.
};

ConstIncorrect::ConstIncorrect(Field& f) : fld(f) {} // Modifies.
Field& ConstIncorrect::getField() { return fld; }    // Doesn't modify.
void ConstIncorrect::setField(Field& f) { fld = f; } // Modifies.
void ConstIncorrect::doSomething(int i) {            // Modifies.
    fld.insert_value(i);
}
void ConstIncorrect::doNothing() {}                  // Doesn't modify.


class ConstCorrectCVQ {
    Field fld;

  public:
    ConstCorrectCVQ(Field& f);     // Modifies.

    const Field& getField() const; // Doesn't modify.  Exposes member as const reference,
                                   //  preventing indirect modification.
    void setField(Field& f);       // Modifies.

    void doSomething(int i);       // Modifies.
    void doNothing() const;        // Doesn't modify.
};

ConstCorrectCVQ::ConstCorrectCVQ(Field& f) : fld(f) {}
Field& ConstCorrectCVQ::getField() const { return fld; }
void ConstCorrectCVQ::setField(Field& f) { fld = f; }
void ConstCorrectCVQ::doSomething(int i) {
    fld.insert_value(i);
}
void ConstCorrectCVQ::doNothing() const  {}

// This won't work.
// No member functions can be called on const ConstIncorrect instances.
void const_correct_func(const ConstIncorrect& c) {
    Field f = c.getField();
    c.do_nothing();
}

// But this will.
// getField() and doNothing() can be called on const ConstCorrectCVQ instances.
void const_correct_func(const ConstCorrectCVQ& c) {
    Field f = c.getField();
    c.do_nothing();
}

हम तो साथ इस गठजोड़ कर सकते हैं Const Correct Function Parameters के कारण वर्ग पूरी तरह से होना करने के लिए const -correct।

class ConstCorrect {
    Field fld;

  public:
    ConstCorrect(const Field& f);  // Modifies instance.  Doesn't modify parameter.

    const Field& getField() const; // Doesn't modify.  Exposes member as const reference,
                                   //  preventing indirect modification.
    void setField(const Field& f); // Modifies instance.  Doesn't modify parameter.

    void doSomething(int i);       // Modifies.  Doesn't modify parameter (passed by value).
    void doNothing() const;        // Doesn't modify.
};

ConstCorrect::ConstCorrect(const Field& f) : fld(f) {}
Field& ConstCorrect::getField() const { return fld; }
void ConstCorrect::setField(const Field& f) { fld = f; }
void ConstCorrect::doSomething(int i) {
    fld.insert_value(i);
}
void ConstCorrect::doNothing() const {}

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

class ConstCorrectContainer {
    int arr[5];

  public:
    // Subscript operator provides read access if instance is const, or read/write access
    // otherwise.    
          int& operator[](size_t index)       { return arr[index]; }
    const int& operator[](size_t index) const { return arr[index]; }

    // ...
};

यह आमतौर पर मानक पुस्तकालय में उपयोग किया जाता है, जिसमें अधिकांश कंटेनर const प्रदान करते हैं ताकि कॉन्स्टेंस को ध्यान में रखा जा सके।

कांस्टिट्यूशन फंक्शन पैरामीटर

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

struct Example {
    void func()       { std::cout << 3 << std::endl; }
    void func() const { std::cout << 5 << std::endl; }
};

void const_incorrect_function(Example& one, Example* two) {
    one.func();
    two->func();
}

void const_correct_function(const Example& one, const Example* two) {
    one.func();
    two->func();
}

int main() {
    Example a, b;
    const_incorrect_function(a, &b);
    const_correct_function(a, &b);
}

// Output:
3
3
5
5

हालांकि इस के प्रभाव कम तुरंत दिखाई की तुलना में कर रहे हैं const सही वर्ग डिजाइन (कि में const -correct कार्यों और const -incorrect कक्षाएं होगा संकलन त्रुटियों का कारण है, जबकि const -correct वर्गों और const -incorrect कार्यों ठीक से संकलित कर देगा), const सही फ़ंक्शंस बहुत सारी गलतियाँ const जो कि गलत फ़ंक्शंस को नीचे से फिसलने देंगी, जैसे नीचे दिया गया है। [ध्यान दें, तथापि, कि एक const एक पारित कर दिया है, तो होगा -incorrect समारोह संकलन त्रुटियों का कारण const उदाहरण है जब यह एक गैर उम्मीद const एक।]

// Read value from vector, then compute & return a value.
// Caches return values for speed.
template<typename T>
const T& bad_func(std::vector<T>& v, Helper<T>& h) {
    // Cache values, for future use.
    // Once a return value has been calculated, it's cached & its index is registered.
    static std::vector<T> vals = {};

    int v_ind = h.get_index();               // Current working index for v.
    int vals_ind = h.get_cache_index(v_ind); // Will be -1 if cache index isn't registered.

    if (vals.size() && (vals_ind != -1) && (vals_ind < vals.size()) && !(h.needs_recalc())) {
        return vals[h.get_cache_index(v_ind)];
    }

    T temp = v[v_ind];

    temp -= h.poll_device();
    temp *= h.obtain_random();
    temp += h.do_tedious_calculation(temp, v[h.get_last_handled_index()]);

    // We're feeling tired all of a sudden, and this happens.
    if (vals_ind != -1) {
        vals[vals_ind] = temp;
    } else {
        v.push_back(temp);  // Oops.  Should've been accessing vals.
        vals_ind = vals.size() - 1;
        h.register_index(v_ind, vals_ind);
    }

    return vals[vals_ind];
}

// Const correct version.  Is identical to above version, so most of it shall be skipped.
template<typename T>
const T& good_func(const std::vector<T>& v, Helper<T>& h) {
    // ...

    // We're feeling tired all of a sudden, and this happens.
    if (vals_ind != -1) {
        vals[vals_ind] = temp;
    } else {
        v.push_back(temp);  // Error: discards qualifiers.
        vals_ind = vals.size() - 1;
        h.register_index(v_ind, vals_ind);
    }

    return vals[vals_ind];
}

दस्तावेज़ीकरण के रूप में कांस्टीट्यूशन सही

const शुद्धता के बारे में अधिक उपयोगी चीजों में से एक यह है कि यह कोडिंग दस्तावेज़ के एक तरीके के रूप में कार्य करता है, जो प्रोग्रामर और अन्य उपयोगकर्ताओं को कुछ गारंटी प्रदान करता है। ये गारंटी देता है की वजह संकलक द्वारा लागू की गई हैं const की कमी के साथ, सत्ता const कि कोड उन्हें प्रदान नहीं करता है यह दर्शाता है बदले में सत्ता।

const CV-योग्य सदस्य कार्य:

  • कोई भी सदस्य फ़ंक्शन जो const , उसे उदाहरण पढ़ने के इरादे से माना जा सकता है, और:
    • जिस उदाहरण पर उन्हें बुलाया जाता है, उसकी तार्किक स्थिति को संशोधित नहीं करेंगे। इसलिए, वे उस उदाहरण के किसी भी सदस्य चर को संशोधित नहीं करेंगे, जो उन्हें कहा जाता है, केवल mutable चर को छोड़कर।
    • किसी भी अन्य फ़ंक्शन को कॉल नहीं करेगा जो कि mutable चर को छोड़कर, उदाहरण के किसी भी सदस्य चर को संशोधित करेगा।
  • इसके विपरीत, कोई भी सदस्य फ़ंक्शन जो const नहीं करता है उसे उदाहरण को संशोधित करने का इरादा माना जा सकता है, और:
    • तार्किक स्थिति को बदल सकता है या नहीं भी कर सकता है।
    • मई या अन्य कार्यों को कॉल नहीं कर सकता है जो तार्किक स्थिति को संशोधित करते हैं।

इसका उपयोग किसी दिए गए सदस्य फ़ंक्शन को कॉल करने के बाद ऑब्जेक्ट की स्थिति के बारे में धारणा बनाने के लिए किया जा सकता है, यहां तक कि उस फ़ंक्शन की परिभाषा को देखे बिना:

// ConstMemberFunctions.h

class ConstMemberFunctions {
    int val;
    mutable int cache;
    mutable bool state_changed;

  public:
    // Constructor clearly changes logical state.  No assumptions necessary.
    ConstMemberFunctions(int v = 0);

    // We can assume this function doesn't change logical state, and doesn't call
    //  set_val().  It may or may not call squared_calc() or bad_func().
    int calc() const;

    // We can assume this function doesn't change logical state, and doesn't call
    //  set_val().  It may or may not call calc() or bad_func().
    int squared_calc() const;

    // We can assume this function doesn't change logical state, and doesn't call
    //  set_val().  It may or may not call calc() or squared_calc().
    void bad_func() const;

    // We can assume this function changes logical state, and may or may not call
    //  calc(), squared_calc(), or bad_func().
    void set_val(int v);
};

const नियमों के कारण, इन मान्यताओं को वास्तव में संकलक द्वारा लागू किया जाएगा।

// ConstMemberFunctions.cpp

ConstMemberFunctions::ConstMemberFunctions(int v /* = 0*/)
  : cache(0), val(v), state_changed(true) {}

// Our assumption was correct.
int ConstMemberFunctions::calc() const {
    if (state_changed) {
        cache = 3 * val;
        state_changed = false;
    }

    return cache;
}

// Our assumption was correct.
int ConstMemberFunctions::squared_calc() const {
    return calc() * calc();
}

// Our assumption was incorrect.
// Function fails to compile, due to `this` losing qualifiers.
void ConstMemberFunctions::bad_func() const {
    set_val(863);
}

// Our assumption was correct.
void ConstMemberFunctions::set_val(int v) {
    if (v != val) {
        val = v;
        state_changed = true;
    }
}

const समारोह पैरामीटर:

  • एक या एक से अधिक मापदंडों के साथ कोई भी कार्य जो const हैं मान सकते हैं कि उन मापदंडों को पढ़ने का इरादा है, और:
    • उन मापदंडों को संशोधित नहीं करेंगे, या किसी भी सदस्य कार्यों को कॉल करेंगे जो उन्हें संशोधित करेगा।
    • उन मापदंडों को किसी अन्य फ़ंक्शन में पास नहीं करेंगे जो उन्हें संशोधित करेगा और / या किसी भी सदस्य फ़ंक्शन को कॉल करेगा जो उन्हें संशोधित करेगा।
  • इसके विपरीत, एक या एक से अधिक मापदंडों के साथ कोई भी कार्य जो const नहीं कर रहे हैं, उन मापदंडों को संशोधित करने का इरादा माना जा सकता है, और:
    • मई या उन मापदंडों को संशोधित नहीं कर सकता है, या किसी भी सदस्य कार्यों को कॉल करता है जो उन्हें संशोधित करते हैं।
    • मई या उन मापदंडों को अन्य कार्यों के लिए पारित नहीं कर सकता है जो उन्हें संशोधित करेगा और / या किसी भी सदस्य फ़ंक्शन को कॉल करेगा जो उन्हें संशोधित करेगा।

इसका उपयोग किसी भी फ़ंक्शन को दिए जाने के बाद मापदंडों की स्थिति के बारे में धारणा बनाने के लिए किया जा सकता है, यहां तक कि उस फ़ंक्शन की परिभाषा को देखे बिना भी।

// function_parameter.h

// We can assume that c isn't modified (and c.set_val() isn't called), and isn't passed
//  to non_qualified_function_parameter().  If passed to one_const_one_not(), it is the first
//  parameter.
void const_function_parameter(const ConstMemberFunctions& c);

// We can assume that c is modified and/or c.set_val() is called, and may or may not be passed
//  to any of these functions.  If passed to one_const_one_not, it may be either parameter.
void non_qualified_function_parameter(ConstMemberFunctions& c);

// We can assume that:
  // l is not modified, and l.set_val() won't be called.
  // l may or may not be passed to const_function_parameter().
  // r is modified, and/or r.set_val() may be called.
  // r may or may not be passed to either of the preceding functions.
void one_const_one_not(const ConstMemberFunctions& l, ConstMemberFunctions& r);

// We can assume that c isn't modified (and c.set_val() isn't called), and isn't passed
//  to non_qualified_function_parameter().  If passed to one_const_one_not(), it is the first
//  parameter.
void bad_parameter(const ConstMemberFunctions& c);

const नियमों के कारण, इन मान्यताओं को वास्तव में संकलक द्वारा लागू किया जाएगा।

// function_parameter.cpp

// Our assumption was correct.
void const_function_parameter(const ConstMemberFunctions& c) {
    std::cout << "With the current value, the output is: " << c.calc() << '\n'
              << "If squared, it's: " << c.squared_calc()
              << std::endl;
}

// Our assumption was correct.
void non_qualified_function_parameter(ConstMemberFunctions& c) {
    c.set_val(42);
    std::cout << "For the value 42, the output is: " << c.calc() << '\n'
              << "If squared, it's: " << c.squared_calc()
              << std::endl;
}

// Our assumption was correct, in the ugliest possible way.
// Note that const correctness doesn't prevent encapsulation from intentionally being broken,
//  it merely prevents code from having write access when it doesn't need it.
void one_const_one_not(const ConstMemberFunctions& l, ConstMemberFunctions& r) {
    // Let's just punch access modifiers and common sense in the face here.
    struct Machiavelli {
        int val;
        int unimportant;
        bool state_changed;
    };
    reinterpret_cast<Machiavelli&>(r).val = l.calc();
    reinterpret_cast<Machiavelli&>(r).state_changed = true;

    const_function_parameter(l);
    const_function_parameter(r);
}

// Our assumption was incorrect.
// Function fails to compile, due to `this` losing qualifiers in c.set_val().
void bad_parameter(const ConstMemberFunctions& c) {
    c.set_val(18);
}

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

class DealBreaker : public ConstMemberFunctions {
  public:
    DealBreaker(int v = 0);

    // A foreboding name, but it's const...
    void no_guarantees() const;
}

DealBreaker::DealBreaker(int v /* = 0 */) : ConstMemberFunctions(v) {}

// Our assumption was incorrect.
// const_cast removes const-ness, making the compiler think we know what we're doing.
void DealBreaker::no_guarantees() const {
    const_cast<DealBreaker*>(this)->set_val(823);
}

// ...

const DealBreaker d(50);
d.no_guarantees(); // Undefined behaviour: d really IS const, it may or may not be modified.

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



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow