c++ - सी++ स्थैतिक निरंतर स्ट्रिंग(कक्षा सदस्य)




string class (7)

इन-क्लास प्रारंभिक वाक्यविन्यास का उपयोग करने के लिए, निरंतर अभिव्यक्ति द्वारा प्रारंभिक अभिन्न या गणना प्रकार का स्थिर स्थिर होना चाहिए।

यह प्रतिबंध है। इसलिए, इस मामले में आपको कक्षा के बाहर परिवर्तनीय परिभाषित करने की आवश्यकता है। @AndreyT से answwer देखें

मैं एक वर्ग के लिए एक निजी स्थिर स्थिर होना चाहता हूं (इस मामले में एक आकृति कारखाना)। मुझे इस तरह का कुछ चाहिए।

class A {
   private:
      static const string RECTANGLE = "rectangle";
}

दुर्भाग्य से मुझे C ++ (g ++) कंपाइलर से सभी प्रकार की त्रुटि मिलती है, जैसे कि:

आईएसओ सी ++ सदस्य 'RECTANGLE' के प्रारंभिकरण को रोकता है

गैर-अभिन्न प्रकार 'std :: string' के स्थिर डेटा सदस्य के अवैध इन-क्लास प्रारंभिक

त्रुटि: 'RECTANGLE' स्थिर बनाते हैं

यह मुझे बताता है कि इस तरह के सदस्य डिजाइन मानक के अनुरूप नहीं है। # डिफाईन निर्देश का उपयोग किए बिना आपके पास निजी शाब्दिक स्थिर (या शायद सार्वजनिक) कैसे है (मैं डेटा वैश्वीकरण की बदसूरतता से बचना चाहता हूं!)

किसी भी मदद की सराहना की है। धन्यवाद।


आप या तो ऊपर वर्णित const char* समाधान के लिए जा सकते हैं, लेकिन फिर यदि आपको हर समय स्ट्रिंग की आवश्यकता होती है, तो आपके पास बहुत अधिक ओवरहेड होगा।
दूसरी तरफ, स्थिर स्ट्रिंग को गतिशील प्रारंभिकता की आवश्यकता होती है, इस प्रकार यदि आप किसी अन्य वैश्विक / स्थिर चर के प्रारंभिकरण के दौरान अपने मूल्य का उपयोग करना चाहते हैं, तो आप प्रारंभिक क्रम की समस्या को दबा सकते हैं। इससे बचने के लिए, सबसे सस्ता चीज एक स्टेटर स्ट्रिंग ऑब्जेक्ट को गेटटर के माध्यम से एक्सेस कर रही है, जो जांचती है कि क्या आपका ऑब्जेक्ट प्रारंभ हुआ है या नहीं।

//in a header  
class A{  
  static string s;   
public:   
  static string getS();  
};  
//in implementation  
string A::s;  
namespace{  
  bool init_A_s(){  
    A::s = string("foo");   
    return true;  
  }  
  bool A_s_initialized = init_A_s();  
}  
string A::getS(){      
  if (!A_s_initialized)  
    A_s_initialized = init_A_s();  
  return s;  
}  

केवल A::getS() उपयोग करना याद रखें। चूंकि कोई भी थ्रेडिंग केवल main() द्वारा शुरू किया जा सकता है, और A_s_initialized को main() से पहले प्रारंभ किया गया है, तो आपको A_s_initialized वातावरण में भी ताले की आवश्यकता नहीं है। A_s_initialized डिफ़ॉल्ट रूप से 0 (गतिशील प्रारंभिकरण से पहले) है, इसलिए यदि आप प्रारंभ होने से पहले getS() उपयोग करते हैं, तो आप getS() फ़ंक्शन को सुरक्षित रूप से कॉल करते हैं।

बीटीडब्ल्यू, ऊपर दिए गए उत्तर में: " स्थैतिक कॉन्स std :: स्ट्रिंग RECTANGLE () const ", स्थैतिक फ़ंक्शंस const नहीं हो सकते हैं क्योंकि अगर कोई ऑब्जेक्ट वैसे भी वे राज्य को नहीं बदल सकते हैं (इस पॉइंटर नहीं है)।


कक्षा परिभाषाओं के अंदर आप केवल स्थिर सदस्यों की घोषणा कर सकते हैं। उन्हें कक्षा के बाहर परिभाषित किया जाना है । संकलन-समय अभिन्न स्थिरांक के लिए मानक अपवाद बनाता है कि आप सदस्यों को "प्रारंभ" कर सकते हैं। हालांकि, यह अभी भी एक परिभाषा नहीं है। पता लेना परिभाषा के बिना काम नहीं करेगा, उदाहरण के लिए।

मैं यह उल्लेख करना चाहता हूं कि मुझे स्थिरांक के लिए const char [] पर std :: string का उपयोग करने का लाभ दिखाई नहीं देता है । std :: स्ट्रिंग अच्छा है और सब कुछ लेकिन इसे गतिशील प्रारंभिकता की आवश्यकता है। तो, अगर आप कुछ लिखते हैं

const std::string foo = "hello";

नामस्थान स्कोप पर foo का कन्स्ट्रक्टर मुख्य प्रारंभ के निष्पादन से ठीक पहले चलाया जाएगा और यह कन्स्ट्रक्टर हीप मेमोरी में निरंतर "हैलो" की एक प्रति बनायेगा। जब तक आपको वास्तव में एक std :: स्ट्रिंग होने के लिए RECTANGLE की आवश्यकता नहीं है, तो आप बस लिख सकते हैं

// class definition with incomplete static member could be in a header file
class A {
    static const char RECTANGLE[];
};

// this needs to be placed in a single translation unit only
const char A::RECTANGLE[] = "rectangle";

क्या आप वहां मौजूद हैं! कोई ढेर आवंटन, कोई प्रतिलिपि नहीं, कोई गतिशील प्रारंभिकरण नहीं।

चीयर्स, एस।


यह केवल अतिरिक्त जानकारी है, लेकिन यदि आप वास्तव में हेडर फ़ाइल में स्ट्रिंग चाहते हैं, तो कुछ ऐसा करने का प्रयास करें:

class foo
{
public:
    static const std::string& RECTANGLE(void)
    {
        static const std::string str = "rectangle";

        return str;
    }
};

हालांकि मुझे संदेह है कि इसकी सिफारिश की गई है।


श्रेणी स्थिर चर को हेडर में घोषित किया जा सकता है लेकिन एक .cpp फ़ाइल में परिभाषित किया जाना चाहिए। ऐसा इसलिए है क्योंकि एक स्थैतिक चर का केवल एक उदाहरण हो सकता है और संकलक यह निर्धारित नहीं कर सकता कि जेनरेट की गई ऑब्जेक्ट फ़ाइल इसे रखने के लिए है, इसलिए आपको निर्णय लेना होगा।

सी ++ 11 में घोषणा के साथ स्थिर मूल्य की परिभाषा को रखने के लिए एक नेस्टेड स्थिर संरचना का उपयोग किया जा सकता है। इस मामले में स्थिर सदस्य एक संरचना है और उसे .cpp फ़ाइल में परिभाषित किया जाना है, लेकिन मान शीर्षलेख में हैं।

class A
{
private:
  static struct _Shapes {
     const std::string RECTANGLE {"rectangle"};
     const std::string CIRCLE {"circle"};
  } shape;
};

व्यक्तिगत सदस्यों को शुरू करने के बजाय पूरी स्थैतिक संरचना को .cpp में प्रारंभ किया गया है:

A::_Shapes A::shape;

मूल्यों के साथ उपयोग किया जाता है

A::shape.RECTANGLE;

या - चूंकि सदस्य निजी हैं और इसका उपयोग केवल ए - के साथ किया जाना है

shape.RECTANGLE;

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

// file.h
class File {
public:
  static struct _Extensions {
    const std::string h{ ".h" };
    const std::string hpp{ ".hpp" };
    const std::string c{ ".c" };
    const std::string cpp{ ".cpp" };
  } extension;
};

// file.cpp
File::_Extensions File::extension;

// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };

इस मामले में स्थिर परिवर्तक शीर्षलेख में लिंकर द्वारा बनाए गए प्रारंभिक क्रम के क्रम के आधार पर या तो {""} या {".h", ".hpp"} होगा।

जैसा कि @ abyss.7 द्वारा उल्लेखित किया गया है, यदि आप चर के समय पर चर के मूल्य की गणना की जा सकती है तो आप constexpr का भी उपयोग कर सकते हैं। लेकिन यदि आप static constexpr const char* साथ अपने तार घोषित करते हैं और आपका प्रोग्राम std::string का उपयोग करता है अन्यथा एक ओवरहेड होगा क्योंकि हर बार जब आप इस तरह के निरंतर उपयोग करते हैं तो एक नई std::string ऑब्जेक्ट बनाई जाएगी:

class A {
public:
   static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
   foo(A::STRING); // a new std::string is constructed and destroyed.
}

संभव है बस करें:

static const std::string RECTANGLE() const {
    return "rectangle";
} 

या

#define RECTANGLE "rectangle"

सी ++ में आप अब कर सकते हैं:

class A {
 private:
  static constexpr const char* STRING = "some useful string constant";
};




const