C ++ में निजी स्थिर सदस्यों को कैसे आरंभ करें?


518

C ++ में एक निजी, स्थिर डेटा सदस्य को आरम्भ करने का सबसे अच्छा तरीका क्या है? मैंने अपनी हेडर फ़ाइल में यह कोशिश की, लेकिन यह मुझे अजीब लिंकर त्रुटियाँ देता है:

class foo
{
    private:
        static int i;
};

int foo::i = 0;

मैं यह अनुमान लगा रहा हूं क्योंकि मैं कक्षा के बाहर से किसी निजी सदस्य को इनिशियलाइज़ नहीं कर सकता। तो ऐसा करने का सबसे अच्छा तरीका क्या है?


2
हाय जेसन। मुझे स्थैतिक सदस्यों (डिफ़ॉल्ट अभिन्न) के प्रारंभिक आरंभ पर टिप्पणी नहीं मिली। वास्तव में आपको int foo लिखने की जरूरत है :: मैं ताकि लिंकर इसे ढूंढ सके, लेकिन यह स्वतः 0 के साथ आरंभीकृत हो जाएगा! यह पंक्ति पर्याप्त होगी: int foo :: i; (यह स्टैटिक मेमोरी में संग्रहीत सभी ऑब्जेक्ट्स के लिए मान्य है, लिंकर स्टैटिक ऑब्जेक्ट्स को इनिशियलाइज़ करने के लिए प्रभारी है।)
निको

1
नीचे दिए गए उत्तर टेम्पलेट वर्ग के लिए लागू नहीं होते हैं। वे कहते हैं: आरंभीकरण को स्रोत फ़ाइल में जाना चाहिए। एक टेम्पलेट वर्ग के लिए, यह न तो संभव है, न ही आवश्यक है।
जोचिम डब्ल्यू

7
C ++ 17 स्थैतिक डेटा सदस्यों के इनलाइन आरंभीकरण की अनुमति देता है (यहां तक ​​कि गैर-पूर्णांक प्रकारों के लिए) inline static int x[] = {1, 2, 3};:। En.cppreference.com/w/cpp/language/static#Static_data_members
व्लादिमीर

जवाबों:


556

वर्ग घोषणा हेडर फ़ाइल में होनी चाहिए (या यदि साझा नहीं की गई तो स्रोत फ़ाइल में)।
फ़ाइल: foo.h

class foo
{
    private:
        static int i;
};

लेकिन आरंभीकरण स्रोत फ़ाइल में होना चाहिए।
फ़ाइल: foo.cpp

int foo::i = 0;

यदि आरंभीकरण हेडर फ़ाइल में है, तो हेडर फ़ाइल में शामिल प्रत्येक फ़ाइल में स्थिर सदस्य की परिभाषा होगी। इस प्रकार लिंक चरण के दौरान आपको लिंकर त्रुटियां मिलेंगी क्योंकि चर को आरंभ करने के लिए कोड को कई स्रोत फ़ाइलों में परिभाषित किया जाएगा। की initialisation static int iकिसी भी समारोह के बाहर किया जाना चाहिए।

नोट: मैट कर्टिस: अंक बाहर सी ++ के सरलीकरण की अनुमति देता है कि इसके बाद के संस्करण यदि स्थिर सदस्य चर स्थिरांक पूर्णांक प्रकार का है (उदाहरण के लिए int, bool, char)। तब आप शीर्ष लेख फ़ाइल में सीधे वर्ग घोषणा के अंदर सदस्य चर घोषित और शुरू कर सकते हैं:

class foo
{
    private:
        static int const i = 42;
};

4
हाँ। लेकिन मैं मान रहा हूं कि प्रश्न को सरल बनाया गया है। तकनीकी रूप से घोषणा और परिभाषा सभी एक स्रोत फ़ाइल में हो सकती है। लेकिन इसके बाद अन्य वर्गों द्वारा कक्षा के उपयोग को सीमित कर दिया जाता है।
मार्टिन यॉर्क

11
वास्तव में सिर्फ POD नहीं है, यह एक इंट टाइप होने के साथ-साथ (int, short, bool, char ...)
मैट कर्टिस

9
ध्यान दें कि यह केवल एक सवाल नहीं है कि मूल्य कैसे आरंभ किया गया है: इस तरह परिभाषित कांस्टेबल अभिन्न प्रकार कार्यान्वयन द्वारा संकलित समय स्थिरांक में बदल सकते हैं। यह हमेशा वह नहीं होता है जो आप चाहते हैं, क्योंकि यह द्विआधारी निर्भरता को बढ़ाता है: यदि मूल्य में परिवर्तन होता है तो क्लाइंट कोड को पुनर्संयोजन की आवश्यकता होती है।
स्टीव जेसप

5
@ मर्टिन: करेक्शन एस / पीओडी / इंटीग्रल टाइप / के अलावा, अगर एड्रेस कभी लिया जाता है तो उसकी भी परिभाषा होनी चाहिए। अजीब लग सकता है क्योंकि यह लग सकता है, वर्ग परिभाषा में इनिलाइज़र के साथ घोषणा, एक परिभाषा नहीं है। टेम्प्लेट की स्थिरांक मुहावरा मामलों में आप किसी हेडर फाइल में परिभाषा की जरूरत के लिए एक समाधान प्रदान करता है। अन्य और सरल वर्कअराउंड एक फ़ंक्शन है जो स्थानीय स्थिर स्थिरांक का मान पैदा करता है। चीयर्स एंड हथ।
चीयर्स एंड हथ। - अल्फ

3
आप एक स्पष्टीकरण जोड़ सकते हैं कि int foo :: i = 0; एक फ़ंक्शन (मुख्य फ़ंक्शन सहित) के अंदर नहीं होना चाहिए। मेरे पास मेरे मुख्य समारोह की शुरुआत में यह था और यह ऐसा नहीं करता है।
qwerty9967

89

एक चर के लिए :

foo.h:

class foo
{
private:
    static int i;
};

foo.cpp:

int foo::i = 0;

ऐसा इसलिए है क्योंकि foo::iआपके कार्यक्रम में केवल एक ही उदाहरण हो सकता है । यह extern int iएक हेडर फ़ाइल के बराबर है और int iएक स्रोत फ़ाइल में है।

एक स्थिर के लिए आप मूल्य को सीधे वर्ग घोषणा में रख सकते हैं:

class foo
{
private:
    static int i;
    const static int a = 42;
};

2
यह एक मान्य बिंदु है। मैं इसे भी अपने स्पष्टीकरण में जोड़ दूंगा। लेकिन यह ध्यान दिया जाना चाहिए कि यह केवल POD प्रकारों के लिए काम करता है।
मार्टिन यॉर्क

कब से, C ++ केवल इन-क्लास घोषणा के साथ अच्छा है और अभिन्न प्रकार के लिए कोई परिभाषा नहीं देता है। C ++ 98 के बाद से या C ++ 03 या कब? कृपया प्रामाणिक लिंक साझा करें। सी ++ मानक शब्दांकन कंपाइलरों के साथ सिंक में नहीं है। वे उल्लेख करते हैं कि सदस्य अभी भी परिभाषित किया जाएगा यदि उनका उपयोग किया जाता है। इसलिए, मुझे C ++ मानक की आवश्यकता नहीं है, हालांकि
smRaj

1
मुझे आश्चर्य है कि क्यों privateचर को कक्षा के बाहर आरम्भ किया जा सकता है, क्या यह गैर-स्थैतिक चर के लिए भी किया जा सकता है।
कृष्णा ओझा

क्या आपने स्पष्टीकरण पाया है? @ कृष्ण_ओज़ा
nn0p १४'१६ को

@ nn0p अभी तक नहीं है, लेकिन बाहर गैर-निजी निजी चर आरंभीकरण Cpp में कोई Classमतलब नहीं है।
कृष्णा ओझा

41

C ++ 17 के बाद से, स्थैतिक सदस्यों को इनलाइन कीवर्ड के साथ हेडर में परिभाषित किया जा सकता है ।

http://en.cppreference.com/w/cpp/language/static

"एक स्थैतिक डेटा सदस्य को इनलाइन घोषित किया जा सकता है। एक इनलाइन स्थैतिक डेटा सदस्य को वर्ग परिभाषा में परिभाषित किया जा सकता है और यह एक डिफ़ॉल्ट सदस्य इनिशियलाइज़र निर्दिष्ट कर सकता है। इसे एक आउट-ऑफ-क्लास परिभाषा की आवश्यकता नहीं है:"

struct X
{
    inline static int n = 1;
};

1
यह C ++ 17 के बाद से संभव है, जो वर्तमान में नए मानक बनने की प्रगति में है।
ग्रैबू

31

इस प्रश्न के भविष्य के दर्शकों के लिए, मैं यह बताना चाहता हूं कि आपको बंदर से बचना चाहिए ।

हेडर फाइलें घोषणाओं के लिए हैं।

हेडर फाइलें हर .cppफ़ाइल के लिए एक बार संकलित हो जाती हैं जो प्रत्यक्ष या अप्रत्यक्ष रूप से होती #includesहैं, और किसी भी फ़ंक्शन के बाहर कोड प्रोग्राम इनिशियलाइज़ेशन से पहले चलाया जाता है main()

डालकर: foo::i = VALUE;शीर्ष लेख में, हर फ़ाइल के लिए foo:iमान VALUE(जो कुछ भी है) .cppसौंपा जाएगा, और ये असाइनमेंट main()चलने से पहले एक अनिश्चित क्रम (लिंकर द्वारा निर्धारित) में होगा ।

क्या होगा यदि हम #define VALUEअपनी .cppफ़ाइलों में से एक में एक अलग संख्या हो ? यह ठीक संकलित करेगा और हमारे पास यह जानने का कोई तरीका नहीं होगा कि कार्यक्रम चलाने तक कौन जीते।

कभी भी #includeएक .cppफ़ाइल के लिए एक हेडर में निष्पादित कोड नहीं डाला जाता है कि आप कभी फ़ाइल नहीं करते हैं।

गार्ड्स को शामिल करें (जो मैं मानता हूं कि आपको हमेशा उपयोग करना चाहिए) आपको कुछ अलग करने से बचाता है: एक ही हेडर अप्रत्यक्ष रूप से #includeएक ही .cppफाइल को संकलित करते हुए कई बार होता है।


2
आप निश्चित रूप से इस बारे में सही हैं, एक वर्ग टेम्पलेट के मामले को छोड़कर (जिसके बारे में नहीं पूछा गया है, लेकिन मैं बहुत से व्यवहार करता हूं)। इसलिए यदि क्लास पूरी तरह से परिभाषित है और क्लास टेम्प्लेट नहीं है, तो इन स्टैटिक सदस्यों को एक अलग CPP फ़ाइल में रखें, लेकिन क्लास टेम्प्लेट के लिए परिभाषा एक ही अनुवाद इकाई (जैसे, हेडर फ़ाइल) में होनी चाहिए।
बंदर ०५०६

@ बंदर_05_06: यह सिर्फ अस्थायी कोड में स्थिर सदस्य से बचने के लिए एक तर्क लगता है: आप पहले से ही कक्षा के प्रत्येक तात्कालिकता के लिए एक स्थिर सदस्य के साथ समाप्त होते हैं। समस्या को संभवतः कई सीपीपी फाइलों में हेडर संकलित करके खराब कर दिया जाता है ... आप परस्पर विरोधी परिभाषाओं का बेड़ा प्राप्त कर सकते हैं।
जोशुआ क्लेटन

publib.boulder.ibm.com/infocenter/macxhelp/v6v81/… इस लिंक में स्टेटिक टेम्पलेट में तत्काल इंस्टेंटेटिंग के सदस्यों को दर्शाया गया है, जो कि एक बोझ होने पर मुख्य फंक्शन को क्लीनर बनाता है
जोशुआ क्लेटन

1
आपका तर्क वास्तव में बहुत बड़ा है। सबसे पहले आप # वेलफाइन वैल्यू नहीं बना सकते क्योंकि मैक्रोज़ नाम ओटी का एक मान्य पहचानकर्ता है। और यहां तक ​​कि अगर आप कर सकते हैं - तो वह कौन करेगा? हैडर फाइलें घोषणा के लिए हैं -? C'mon .. केवल उन मामलों में जहां आपको हेडर में मान डालने से बचना चाहिए, ओड-यूज्ड से लड़ना है। और जब भी आपको मूल्य बदलने की आवश्यकता होती है, तो हेडर में मूल्य डालने से अनावश्यक पुनर्मूल्यांकन हो सकता है।
अलेक्जेंडर फुलार

20

Microsoft कंपाइलर [1] के साथ, स्थिर वैरिएबल जो समान नहीं हैं, intउन्हें भी हेडर फ़ाइल में परिभाषित किया जा सकता है, लेकिन वर्ग विशेष के बाहर, Microsoft विशिष्ट का उपयोग करके __declspec(selectany)

class A
{
    static B b;
}

__declspec(selectany) A::b;

ध्यान दें कि मैं यह नहीं कह रहा हूं कि यह अच्छा है, मैं कहता हूं कि यह किया जा सकता है।

[१] इन दिनों, MSC समर्थन से अधिक संकलक __declspec(selectany)- कम से कम gcc और clang। शायद और भी ज्यादा।


17
int foo::i = 0; 

वेरिएबल को इनिशियलाइज़ करने के लिए सही सिंटैक्स है, लेकिन इसे हेडर के बजाय सोर्स फाइल (.cpp) में जाना चाहिए।

क्योंकि यह एक स्थिर वैरिएबल है जिसे कंपाइलर को इसकी केवल एक प्रति बनाने की आवश्यकता है। आपके पास एक कोड है "int foo: i" कुछ जहां आपके कोड में संकलक को यह बताना है कि इसे कहां रखा जाए अन्यथा आपको लिंक त्रुटि मिलती है। यदि यह हेडर में है तो आपको हेडर सहित हर फाइल में एक कॉपी मिल जाएगी, इसलिए लिंकर से गुणा की गई सिंबल एरर प्राप्त करें।


12

मेरे पास इसे टिप्पणी के रूप में जोड़ने के लिए यहां पर्याप्त दोहराव नहीं है, लेकिन IMO आपके हेडर को वैसे भी #include गार्ड के साथ लिखने की अच्छी शैली है , जो कुछ घंटों पहले Paranaix द्वारा नोट किया गया था, जो कई-परिभाषा त्रुटि को रोक देगा। जब तक आप पहले से ही एक अलग CPP फ़ाइल का उपयोग नहीं कर रहे हैं, तब तक स्थैतिक गैर-अभिन्न सदस्यों को आरंभ करने के लिए एक का उपयोग करना आवश्यक नहीं है।

#ifndef FOO_H
#define FOO_H
#include "bar.h"

class foo
{
private:
    static bar i;
};

bar foo::i = VALUE;
#endif

मुझे इसके लिए एक अलग CPP फ़ाइल का उपयोग करने की कोई आवश्यकता नहीं है। यकीन है, आप कर सकते हैं, लेकिन कोई तकनीकी कारण नहीं है कि आपको क्यों होना चाहिए।


21
# प्रतिसाद गार्ड केवल अनुवाद इकाई प्रति कई परिभाषाओं को रोकने के।
पॉल फुल्ट्ज II

3
अच्छी शैली के बारे में: आपको समापन समाप्ति पर टिप्पणी जोड़ना चाहिए:#endif // FOO_H
रीगा

9
यह केवल तभी काम करता है जब आपके पास केवल एक संकलन इकाई हो जिसमें foo.h शामिल हो। यदि दो या दो से अधिक cpps में foo.h शामिल है, जो कि एक विशिष्ट स्थिति है, तो प्रत्येक cpp एक ही स्टेटिक वैरिएबल की घोषणा करेगा, इसलिए लिंकर `foo :: i 'की कई परिभाषाओं के साथ शिकायत करेगा जब तक आप फ़ाइलों के साथ एक पैकेज संकलन का उपयोग नहीं करते हैं (संकलन) केवल एक फ़ाइल जिसमें सभी सीपी शामिल हैं)। लेकिन यद्यपि पैकेज संकलन एक समस्या के समाधान के लिए बहुत अच्छा है (int foo :: i = 0);
एलेजाद्रो ज़लाबार्डर

1
या बस का उपयोग करें#pragma once
तमब्रे

12

यदि आप कुछ मिश्रित प्रकार (fe string) को आरंभ करना चाहते हैं, तो आप ऐसा कुछ कर सकते हैं:

class SomeClass {
  static std::list<string> _list;

  public:
    static const std::list<string>& getList() {
      struct Initializer {
         Initializer() {
           // Here you may want to put mutex
           _list.push_back("FIRST");
           _list.push_back("SECOND");
           ....
         }
      }
      static Initializer ListInitializationGuard;
      return _list;
    }
};

जैसा कि ListInitializationGuardएक स्थिर चर के अंदर SomeClass::getList()विधि है, इसका निर्माण केवल एक बार किया जाएगा, जिसका अर्थ है कि निर्माणकर्ता को एक बार कहा जाता है। यह initialize _listआपकी आवश्यकता के मान के अनुसार परिवर्तनशील होगा । किसी भी बाद की कॉल getListकेवल प्रारंभिक _listऑब्जेक्ट को पहले से ही वापस कर देगी ।

बेशक आपको _listकॉलिंग getList()विधि द्वारा हमेशा ऑब्जेक्ट तक पहुंचना होगा ।


1
यहाँ इस मुहावरे का एक संस्करण है जिसमें प्रति सदस्य ऑब्जेक्ट में एक विधि बनाने की आवश्यकता नहीं है: stackoverflow.com/a/48337288/895245
Ciro Santilli 郝海东 this this 事件

9

C ++ 11 स्थिर कंस्ट्रक्टर पैटर्न जो कई वस्तुओं के लिए काम करता है

एक मुहावरे पर प्रस्तावित किया गया था: https://stackoverflow.com/a/27088552/895245 लेकिन यहां एक क्लीनर संस्करण जाता है जिसमें प्रति सदस्य एक नई विधि बनाने की आवश्यकता नहीं होती है।

main.cpp

#include <cassert>
#include <vector>

// Normally on the .hpp file.
class MyClass {
public:
    static std::vector<int> v, v2;
    static struct StaticConstructor {
        StaticConstructor() {
            v.push_back(1);
            v.push_back(2);
            v2.push_back(3);
            v2.push_back(4);
        }
    } _staticConstructor;
};

// Normally on the .cpp file.
std::vector<int> MyClass::v;
std::vector<int> MyClass::v2;
// Must come after every static member.
MyClass::StaticConstructor MyClass::_staticConstructor;

int main() {
    assert(MyClass::v[0] == 1);
    assert(MyClass::v[1] == 2);
    assert(MyClass::v2[0] == 3);
    assert(MyClass::v2[1] == 4);
}

गिटहब ऊपर

संकलित करें और चलाएं:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

यह भी देखें: C ++ में स्थिर निर्माणकर्ता? मुझे निजी स्थिर वस्तुओं को इनिशियलाइज़ करने की आवश्यकता है

उबंटू 19.04 पर परीक्षण किया गया।

C ++ 17 इनलाइन वैरिएबल

इस पर उल्लेख किया गया: https://stackoverflow.com/a/45062055/895245 लेकिन यहाँ यह स्पष्ट करने के लिए एक बहुक्रियाशील उदाहरण है: इनलाइन चर कैसे काम करते हैं?


5

यदि आप हेडर गार्ड का उपयोग करते हैं तो आप हेडर फ़ाइल में असाइनमेंट भी शामिल कर सकते हैं। मैंने इस तकनीक का उपयोग C ++ लाइब्रेरी के लिए किया है जिसे मैंने बनाया है। समान परिणाम प्राप्त करने का एक और तरीका है, स्थैतिक तरीकों का उपयोग करना। उदाहरण के लिए...

class Foo
   {
   public:
     int GetMyStatic() const
     {
       return *MyStatic();
     }

   private:
     static int* MyStatic()
     {
       static int mStatic = 0;
       return &mStatic;
     }
   }

उपरोक्त कोड में CPP / स्रोत फ़ाइल की आवश्यकता नहीं होने का "बोनस" है। फिर, एक विधि जिसका उपयोग मैं अपने C ++ पुस्तकालयों के लिए करता हूं।


4

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

#include <stdio.h>

class Foo
{
   public:

     int   GetMyStaticValue () const {  return MyStatic();  }
     int & GetMyStaticVar ()         {  return MyStatic();  }
     static bool isMyStatic (int & num) {  return & num == & MyStatic(); }

   private:

      static int & MyStatic ()
      {
         static int mStatic = 7;
         return mStatic;
      }
};

int main (int, char **)
{
   Foo obj;

   printf ("mystatic value %d\n", obj.GetMyStaticValue());
   obj.GetMyStaticVar () = 3;
   printf ("mystatic value %d\n", obj.GetMyStaticValue());

   int valMyS = obj.GetMyStaticVar ();
   int & iPtr1 = obj.GetMyStaticVar ();
   int & iPtr2 = valMyS;

   printf ("is my static %d %d\n", Foo::isMyStatic(iPtr1), Foo::isMyStatic(iPtr2));
}

यह आउटपुट है

mystatic value 7
mystatic value 3
is my static 1 0

3

PrivateStatic.cpp फ़ाइल में भी काम कर रहा है:

#include <iostream>

using namespace std;

class A
{
private:
  static int v;
};

int A::v = 10; // possible initializing

int main()
{
A a;
//cout << A::v << endl; // no access because of private scope
return 0;
}

// g++ privateStatic.cpp -o privateStatic && ./privateStatic

3

एक set_default()विधि के बारे में क्या ?

class foo
{
    public:
        static void set_default(int);
    private:
        static int i;
};

void foo::set_default(int x) {
    i = x;
}

हमें केवल set_default(int x)विधि और हमारे उपयोग करने होंगेstatic करना होगा चर को प्रारंभ किया जाएगा।

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


3

आपके द्वारा सामना की गई लिंकर समस्या संभवतः इसके कारण है:

  • हेडर फ़ाइल में वर्ग और स्थिर सदस्य परिभाषा दोनों प्रदान करना,
  • इस हेडर को दो या अधिक स्रोत फ़ाइलों में शामिल करें।

C ++ से शुरू होने वाले लोगों के लिए यह एक आम समस्या है। स्टेटिक क्लास मेंबर को सिंगल ट्रांसलेशन यूनिट यानी सिंगल सोर्स फाइल में इनिशियलाइज़ किया जाना चाहिए।

दुर्भाग्य से, स्थिर वर्ग के सदस्य को वर्ग निकाय के बाहर आरंभ किया जाना चाहिए। यह हेडर-ओनली कोड लिखने में उलझता है, और इसलिए, मैं काफी अलग दृष्टिकोण का उपयोग कर रहा हूं। आप अपने स्थिर ऑब्जेक्ट को उदाहरण के लिए स्थिर या गैर-स्थिर वर्ग फ़ंक्शन के माध्यम से प्रदान कर सकते हैं:

class Foo
{
    // int& getObjectInstance() const {
    static int& getObjectInstance() {
        static int object;
        return object;
    }

    void func() {
        int &object = getValueInstance();
        object += 5;
    }
};

1
मैं अभी भी एक पूर्ण n00b हूँ जहाँ तक C ++ चला जाता है, लेकिन यह मुझे शानदार लगता है, बहुत बहुत धन्यवाद! मुझे मुफ्त में सिंगलटन ऑब्जेक्ट का सही जीवन-चक्र प्रबंधन मिलता है।
राफेल किटओवर

2

स्थिरांक को परिभाषित करने के लिए एक "पुराने-विद्यालय" का तरीका उन्हें एक से बदलना है enum:

class foo
{
    private:
        enum {i = 0}; // default type = int
        enum: int64_t {HUGE = 1000000000000}; // may specify another type
};

इस तरह एक परिभाषा प्रदान करने की आवश्यकता नहीं होती है, और निरंतर अंतराल बनाने से बचा जाता है , जो आपको कुछ सिरदर्द से बचा सकता है, उदाहरण के लिए जब आप गलती से ओडीआर का उपयोग करते हैं।


1

जब मैंने पहली बार इसका सामना किया तो मैं बस कुछ अजीब सा जिक्र करना चाहता था।

मुझे टेम्पलेट क्लास में एक निजी स्थिर डेटा सदस्य को इनिशियलाइज़ करने की आवश्यकता थी।

.h या .hpp में, यह कुछ ऐसा दिखता है, जो किसी टेम्पलेट क्लास के स्थैतिक डेटा सदस्य को इनिशियलाइज़ करता है:

template<typename T>
Type ClassName<T>::dataMemberName = initialValue;

0

क्या यह आपके उद्देश्य को पूरा करता है?

//header file

struct MyStruct {
public:
    const std::unordered_map<std::string, uint32_t> str_to_int{
        { "a", 1 },
        { "b", 2 },
        ...
        { "z", 26 }
    };
    const std::unordered_map<int , std::string> int_to_str{
        { 1, "a" },
        { 2, "b" },
        ...
        { 26, "z" }
    };
    std::string some_string = "justanotherstring";  
    uint32_t some_int = 42;

    static MyStruct & Singleton() {
        static MyStruct instance;
        return instance;
    }
private:
    MyStruct() {};
};

//Usage in cpp file
int main(){
    std::cout<<MyStruct::Singleton().some_string<<std::endl;
    std::cout<<MyStruct::Singleton().some_int<<std::endl;
    return 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.