स्थिर वर्ग के सदस्यों पर अनारक्षित बाहरी प्रतीक


129

बहुत सीधे शब्दों में कहें:

मेरे पास एक वर्ग है जिसमें ज्यादातर स्थिर सार्वजनिक सदस्य हैं, इसलिए मैं समान कार्यों को एक साथ जोड़ सकता हूं जो अभी भी अन्य वर्गों / कार्यों से बुलाए जाने हैं।

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

class test 
{
public:
    static unsigned char X;
    static unsigned char Y;

    ...

    test();
};

test::test() 
{
    X = 1;
    Y = 2;
}

मैं C ++ में नया हूं इसलिए मुझ पर आसानी से जाएं। मैं ऐसा क्यों नहीं कर सकता?

जवाबों:


145

आप एक्स और वाई की अपनी घोषणाओं से मेल खाने वाली परिभाषाओं को जोड़ना भूल गए

unsigned char test::X;
unsigned char test::Y;

कहीं। आप स्थैतिक सदस्य को इनिशियलाइज़ करना भी चाह सकते हैं

unsigned char test::X = 4;

और फिर, आप परिभाषा में (आमतौर पर एक CXX फ़ाइल में) घोषणा में नहीं (जो अक्सर एक .H में होता है) करते हैं।


4
यदि आप हेडर-ओनली लाइब्रेरी लिख रहे हैं, तो आप cpp फ़ाइल से बचने के लिए इस तकनीक का उपयोग कर सकते हैं: stackoverflow.com/questions/11709859/…
शीतल शाह

62

कक्षा की घोषणा में स्टेटिक डेटा सदस्यों की घोषणाएं उनकी परिभाषा नहीं हैं। उन्हें परिभाषित करने के लिए आपको .CPPडुप्लिकेट प्रतीकों से बचने के लिए फ़ाइल में ऐसा करना चाहिए ।

एकमात्र डेटा जिसे आप घोषित कर सकते हैं और परिभाषित कर सकते हैं, वह है अभिन्न स्थिर स्थिरांक। (मूल्यों का enumsउपयोग निरंतर मूल्यों के रूप में भी किया जा सकता है)

आप अपने कोड को फिर से लिखना चाहते हैं:

class test {
public:
  const static unsigned char X = 1;
  const static unsigned char Y = 2;
  ...
  test();
};

test::test() {
}

यदि आप स्थैतिक चर को संशोधित करने की क्षमता चाहते हैं (दूसरे शब्दों में जब उन्हें कांस्ट के रूप में घोषित करना अनुचित है), तो आप निम्नलिखित के बीच .Hऔर नीचे कोड को अलग कर सकते हैं .CPP:

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

.CPP:

unsigned char test::X = 1;
unsigned char test::Y = 2;

test::test()
{
  // constructor is empty.
  // We don't initialize static data member here, 
  // because static data initialization will happen on every constructor call.
}

यहाँ क्यों .CPP में, यह "अहस्ताक्षरित चार परीक्षण :: X = 1;" "परीक्षण :: X = 1?" के बजाय? स्थिर चर एक्स पहले से ही परिभाषित है, फिर भी "अहस्ताक्षरित चार" की आवश्यकता क्यों है? @sergtk
पेनी

@ पेनी क्योंकि "परीक्षण :: एक्स = 1;" एक असाइनमेंट के रूप में व्याख्या की जाती है, जबकि हम जो करने की कोशिश कर रहे हैं वह एक परिभाषा है।
अनाम 1847

4

चूँकि यह पहला SO थ्रेड है जो सामान्य रूप से "स्थैतिक कांस्टेबल सदस्यों के साथ अनसुलझे एक्सटर्नल" की खोज करते समय मेरे लिए आया था, मैं एक और हिंट को एक्सटर्नल एक्सटर्नल के साथ हल करने के लिए छोड़ूँगा:

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


2

मेरे मामले में, मैंने .h फ़ाइल में एक स्थिर चर की तरह घोषित किया

//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}

और myClass.cpp में, मैंने इस m_nMyVar का उपयोग करने का प्रयास किया। इसे लिंक त्रुटि मिली जैसे:

त्रुटि LNK2001: अनसुलझे बाहरी प्रतीक "सार्वजनिक: स्थिर वर्ग ... लिंक त्रुटि संबंधित सीपीपी फ़ाइल की तरह दिखता है:

//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

इसलिए मैं myClass.cpp के शीर्ष पर नीचे कोड जोड़ता हूं

//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

तब LNK2001 चला गया है।


0

मेरे मामले में, मैं गलत लिंकिंग का उपयोग कर रहा था।
इसे c ++ (cli) प्रबंधित किया गया था, लेकिन देशी निर्यात के साथ। मैंने लिंकर -> इनपुट -> असेंबली लिंक संसाधन को लाइब्रेरी के डीएल में जोड़ा है जहां से फ़ंक्शन निर्यात किया जाता है। लेकिन देशी c ++ लिंकिंग के लिए .lib फ़ाइल को cpp में "देख" को सही ढंग से लागू करने की आवश्यकता है, इसलिए मेरे लिए .lib फ़ाइल को लिंकर -> इनपुट -> अतिरिक्त निर्भरता में जोड़ने में मदद की।
[आमतौर पर प्रबंधित कोड dll निर्यात और आयात का उपयोग नहीं करता है, यह संदर्भ का उपयोग करता है, लेकिन यह अनोखी स्थिति थी।]

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