c++ - कंस्ट्रक्टर में कॉन्स्टेबल सदस्यों को क्यों संशोधित किया जा सकता है?




c++11 initialization (2)

मैं उत्सुक हूं कि कंस्ट्रक्टर में कॉन्स्टेबल सदस्यों को क्यों संशोधित किया जा सकता है।

क्या आरंभीकरण में कोई मानक नियम है जो किसी सदस्य के "कास्ट-नेस" से आगे निकल जाता है?

struct Bar {
    const int b = 5; // default member initialization
    Bar(int c):b(c) {}
};

Bar *b = new Bar(2); // Problem: Bar::b is modified to 2
                     // was expecting it to be an error

कोई विचार?


Songyuanyao के महान जवाब में जोड़ना, यदि आप एक कास्ट डेटा सदस्य चाहते हैं जिसे आप एक निर्माता में शुरू नहीं कर सकते हैं, तो आप सदस्य को static बना सकते हैं:

struct Bar {
    static const int b = 5; // static member initialization
    Bar(int c)
        :b(c)        // Error: static data member can only be initialized at its definition
    {
        b = c;       // Error: b is read-only
    }
};

C ++ 17 में आप इसे inline बनाकर इसमें और सुधार कर सकते हैं:

struct Bar {
    inline static const int b = 5; // static member initialization
    Bar(int c)
        :b(c)        // Error: static data member can only be initialized at its definition
    {
        b = c;       // Error: b is read-only
    }
};

इस तरह आपको ODR से कोई समस्या नहीं होगी।


जब तुम करोगे:

struct Bar {
    const int b = 5; // default member initialization
    ...
};

आप कंपाइलर को डिफॉल्ट कंस्ट्रक्टर के साथ ऐसा करने के लिए कह रहे हैं:

...
Bar() : b(5) 
{}
...

भले ही आपने डिफ़ॉल्ट कंस्ट्रक्टर प्रदान किया हो या नहीं। जब आप डिफ़ॉल्ट-निर्माता और प्रारंभिक असाइनमेंट प्रदान करते हैं, तो आप कंपाइलर के डिफ़ॉल्ट असाइनमेंट कोड (यानी b(5) ) को ओवरराइड करते हैं। घोषणा पर डिफ़ॉल्ट आरंभीकरण / असाइनमेंट उपयोगी है जब आपके पास कई निर्माता हैं, और आप सभी निर्माणकर्ताओं में कांस्ट सदस्यों को असाइन या नहीं कर सकते हैं:

...
Bar() = default; // b=5
Bar(int x) : b(x) // b=x
Bar(double y) : /*other init, but not b*/  // b=5
...




const