C ++ में क्लास डिक्लेरेशन के अंदर कॉन्स्टेबल मेंबर को इनिशिएटिव देना


80

PHP और C # में कॉन्स्टेंट को इनिशियलाइज़ किया जा सकता है क्योंकि उन्हें घोषित किया गया है:

class Calendar3
{
    const int value1 = 12;
    const double value2 = 0.001;
}

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

struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    {
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }

    static const float tolerance = 0.001;
};

यह कोड जी ++ की समस्याओं के बिना संकलित है। अब C ++ 0x मोड में (-std = c ++ 0x) g ++ कंपाइलर एक त्रुटि संदेश आउटपुट करता है:

त्रुटि: गैर-अभिन्न प्रकार के स्थैतिक डेटा सदस्य 'सहिष्णुता' के इन-क्लास इनिशियलाइज़ेशन के लिए 'कॉन्स्टैक्सप्र' की आवश्यकता

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

लेकिन क्या वर्ग घोषणा के भीतर एक निरंतर को शुरू करने का कोई तरीका है जैसे कि PHP या C # में संभव है?

अपडेट करें

मैंने staticकीवर्ड का उपयोग सिर्फ इसलिए किया क्योंकि जी + ++ में कक्षा की घोषणा के भीतर ऐसे स्थिरांक को शुरू करना संभव था। मुझे सिर्फ एक वर्ग घोषणा में एक निरंतरता को शुरू करने का एक तरीका चाहिए, चाहे वह घोषित हो staticया न हो।


5
I used static keyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as static or not.यह तय करने का गलत तरीका है कि सदस्य होना चाहिए staticया नहीं। कभी भी शाब्दिक आलस्य को अपने कोड के शब्दार्थ को तय न करने दें।
in पर ऑर्बिट में लाइटनेस दौड़

That's the wrong way to decide whether a member should be static or not.मैं सहमत नहीं हूँ। मुझे लगता है कि निरंतर सदस्यों के लिए कोई फर्क नहीं पड़ता।
ezpresso 19

3
@expresso: बिलकुल नहीं। आप staticउदाहरण-विशिष्ट जानकारी के साथ एक गैर- निरंतर सदस्य को इनिशियलाइज़ कर सकते हैं। आपने तय किया है कि आपका स्थिरांक एक विशिष्ट उदाहरण के बजाय प्रकार की एक संपत्ति है static, इसे बनाने का कारण है , न कि इसलिए कि आपने टाइपिंग शॉर्टकट का उपयोग किया है।
कक्षा

@ प्रकाश: ठीक है, यह संभव है, लेकिन मुझे विभिन्न मूल्यों के साथ एक ही उदाहरण-विशिष्ट स्थिरांक के प्रारंभिक उपयोग का कोई कारण नहीं दिखता है। मैं उस के लिए गैर-कास्ट क्लास फ़ील्ड का उपयोग करता था!
एज़प्रेसो

4
क्यों, अगर वे वस्तु तात्कालिकता के बाद कभी नहीं बदलते हैं? struct myType { const std::time_t instantiated; myType() : instantiated(std::time(0)) {} };सब कुछ है कि कर सकते हैं हो सकता है const चाहिए हो const; यह staticऔर गैर- staticसदस्यों के लिए समान रूप से लागू होता है।
ऑर्बिट

जवाबों:


136

C ++ 11 में, गैर- staticडेटा सदस्य, static constexprडेटा सदस्य, और static constअभिन्न या गणना के डेटा सदस्यों को वर्ग घोषणा में आरंभीकृत किया जा सकता है। जैसे

struct X {
    int i=5;
    const float f=3.12f;
    static const int j=42;
    static constexpr float g=9.5f;
};

इस मामले में, iवर्ग के सभी उदाहरणों के सदस्य को कंपाइलर-जनरेट किए गए कंस्ट्रक्टर द्वारा Xआरंभीकृत किया 5जाता है, और fसदस्य को इसका इनिशियलाइज़ किया जाता है 3.12static constडेटा सदस्य jको आरंभ नहीं हो जाता 42है, और static constexprडेटा सदस्य gको आरंभ नहीं हो जाता 9.5

के बाद से floatऔर doubleअभिन्न या गणना प्रकार के नहीं हैं, इस तरह के सदस्यों को या तो होना चाहिए constexpr, या गैरstatic वर्ग परिभाषा प्रारंभकर्ता के लिए आदेश में अनुमति दी जाए।

C ++ 11 से पहले, केवल static constअभिन्न या गणना प्रकार के डेटा सदस्य वर्ग परिभाषा में इनिशियलाइज़र हो सकते हैं।


वहाँ मानक के हिस्से के लिए एक कड़ी है जहाँ यह कल्पना थी? मैंने अभी इसका उपयोग करना शुरू किया है (सी ++ 14 के रूप में संकलन) और मुझे खुशी है कि यह काम करता है, क्योंकि मैं कंपाइलर को मेरे लिए ऐसा करने से बहुत समय बचाने के लिए खड़ा हूं। हालाँकि, आपके उत्तर को पढ़ने तक, मुझे यकीन नहीं था कि यह काम करना चाहिए! एक आधिकारिक शब्द मेरे आत्मविश्वास को प्रभावित करेगा, हाहा। Fwiw मैं यह char const n[3]{'a', 'b', 'c'};भी सदस्यों की तरह काम कर रहा है ।
अंडरस्कोर_ड

मुझे आश्चर्य है कि क्यों static const intलेकिन static constexpr float? इसका क्या मतलब है float and double are not of integral or enumeration type?
मर्गलूम

@ मर्ग्लूम: हाँ, फ्लोट और डबल नहीं हैं। यदि डेटाटाइप को संपूर्ण संख्या में अनुवादित किया जा सकता है, तो यह एक अभिन्न प्रकार है।
पद्पय

45

स्थैतिक अंतर प्रकारों के अलावा अन्य स्थिर सदस्य चर की शुरुआत मानक C ++ से पहले C ++ 11 मानक नहीं है। जब तक आप -pedanticविकल्प निर्दिष्ट नहीं करते हैं, तब तक gcc संकलक आपको इस बारे में चेतावनी नहीं देगा (और उपयोगी कोड का उत्पादन नहीं करेगा) । फिर आपको निम्न के लिए एक त्रुटि मिलनी चाहिए:

const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression
const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]

इसका कारण यह है कि C ++ मानक यह निर्दिष्ट नहीं करता है कि फ्लोटिंग पॉइंट को कैसे लागू किया जाना चाहिए और प्रोसेसर पर छोड़ दिया जाता है। इसके आसपास और अन्य सीमाओं को प्राप्त करने के लिए constexpr


14

हाँ। जैसे constexprकीवर्ड कहता है वैसे ही ऐड करें ।


1
शायद वह अपनी परियोजना के लिए C ++ 11 की आवश्यकता नहीं करना चाहता है?
मार्क मुत्ज़ - mmutz

6
जिस मुद्दे का वह उल्लेख करते हैं, वह इस तथ्य के कारण पेश किया गया था कि उन्होंने C ++ 11 के रूप में संकलन करने की कोशिश की, यानी वह C ++ 11 :) का समर्थन करना चाहेंगे
Unknown1987

1

यदि आपको केवल एक ही विधि की आवश्यकता है, तो आप इसे स्थानीय रूप से स्थिर घोषित कर सकते हैं:

struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    {
        static const float tolerance = 0.001f;
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }
};

1

मैं इसके साथ वास्तविक समस्याओं में भाग गया, क्योंकि मुझे जी ++ (जीएनयू सी ++ बॉयलर) के विभिन्न संस्करणों के संकलन के लिए समान कोड की आवश्यकता है। इसलिए मुझे यह देखने के लिए मैक्रो का उपयोग करना पड़ा कि संकलक के किस संस्करण का उपयोग किया जा रहा है, और फिर उसी के अनुसार कार्य करें

#if __GNUC__ > 5
 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr
#else
 #define GNU_CONST_STATIC_FLOAT_DECLARATION const
#endif

GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;

यह g ++ संस्करण 6.0.0 से पहले सब कुछ के लिए 'const' का उपयोग करेगा और फिर g ++ संस्करण 6.0.0 और इसके बाद के संस्करण के लिए 'constexpr' का उपयोग करेगा। यह उस संस्करण पर एक अनुमान है जहां परिवर्तन होता है, क्योंकि स्पष्ट रूप से मैंने इसे g ++ संस्करण 6.2.1 तक नोटिस नहीं किया था। इसे सही करने के लिए आपको मामूली संस्करण और g ++ का पैच नंबर देखना पड़ सकता है, इसलिए देखें

https://gcc.gnu.org/onbuildocs/cpp/Common-Predefined-Macros.html

उपलब्ध मैक्रो पर विवरण के लिए।

गन्नू के साथ, आप भी हर जगह 'कास्ट' का उपयोग कर सकते हैं और फिर के साथ संकलन कर सकते हैं -fpermissive झंडे के , लेकिन यह चेतावनी देता है और मुझे अपना सामान साफ-सुथरा संकलन पसंद है।

महान नहीं है, क्योंकि यह गन्न संकलक के लिए विशिष्ट है, लेकिन मुझे संदेह है कि आप अन्य संकलक के साथ भी ऐसा ही कर सकते हैं।

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