2012-07-13 14 views
5

मुझे लगता है कि मुझे नेमस्पेस और/या स्थैतिक चर की मूलभूत गलतफहमी है। लेकिन मैं इस परीक्षण कोड की कोशिश की है (हाथ से टाइप किया, माफ कर लिखने की त्रुटियों)नामस्थान में चर के साथ कैसे काम करें

test.h:

namespace test{ 
    static int testNum=5; 
    void setNum(int value); 
} 

main.cpp:

#include <test.h> 

int test::setNum(int value){ 
    testNum=value; 
} 

int main(){ 
    test::setNum(9); 
    cout<<test::testNum; 
} 

जब मैं इस चलाने मैं मूल्य प्राप्त 5 , 9 नहीं, जैसा कि मैंने उम्मीद की थी। ऐसा लगता है कि मेरे पास testNum चर के दो उदाहरण हैं, लेकिन ऐसा लगता है कि स्थिर क्या करना चाहिए इसके विपरीत यह बिल्कुल विपरीत है। मुझे लगता है कि मैंने यह मानने में गलती की है कि ये सुविधाएं किसी भी तरह उनके जावा इक्विलिंट्स के समान थीं ...

मुझे यह भी एक त्रुटि मिलती है कि testNum को कई बार घोषित किया गया है यदि मैं अपनी घोषणा से स्थिर को हटा देता हूं testNum, क्या कोई समझा सकता है कि यह मामला क्यों है?

धन्यवाद

+1

क्या आप जानते हैं कि '# शामिल' कैसे काम करता है? यह निर्दिष्ट फ़ाइल की सामग्री को कॉपी-पेस्ट करता है। और 'setNum' परिभाषा वास्तव में' main.cpp' में भी है? – Xeo

+0

मैंने इसे नहीं दिखाया, लेकिन मेरे पास मानक। IfndEF DEF है। इसके अलावा, चूंकि मैं इसे केवल एक बार * पूरे कार्यक्रम में शामिल करता हूं, फिर भी यह कोई समस्या नहीं होगी? – dsollen

+0

क्या आप 'नेमस्पेस टेस्ट' का उपयोग करते हैं? –

उत्तर

14

पहले, अपने गलतफहमी कुछ भी नहीं नामस्थान से कोई लेना देना नहीं है, यह केवल बारे में static है। इस उत्तर के बाकी हिस्सों के लिए मैं बस testNum का उल्लेख कर रहा हूं क्योंकि यह एक नामस्थान में मौजूद तथ्य अप्रासंगिक है।

मुझे यह भी लगता है कि आपके पास एक और फ़ाइल है, जिसे शायद test.cpp कहा जाता है, जिसमें test.h भी शामिल है और setNum फ़ंक्शन को परिभाषित करता है।

जब नामस्थान-स्कोप पर एक चर या फ़ंक्शन (यानी वर्ग के सदस्य या किसी फ़ंक्शन के लिए स्थानीय) घोषित नहीं किया जाता है तो static इसका अर्थ यह है कि इकाई का नाम उस फ़ाइल में आंतरिक है। औपचारिक रूप से इसमें "आंतरिक संबंध" है, जिसका अर्थ है कि इसे नाम से संदर्भित नहीं किया जा सकता है या अन्य फ़ाइलों से लिंक नहीं किया जा सकता है (इसे अप्रत्यक्ष रूप से एक सूचक के माध्यम से या किसी अन्य फ़ंक्शन के लिए तर्क के रूप में पारित किया जा सकता है।) इसका अर्थ है कि यदि कई फाइल static int testNum परिभाषित करती हैं, तो प्रत्येक फ़ाइल में उस नाम के साथ अपना आंतरिक आंतरिक चर होता है, जो testNum से अलग होता है, वास्तव में एक फ़ाइल में static int testnum हो सकता है और दूसरा static double testnum और अन्य static char* testNum हो सकता है, वे सभी प्रत्येक के लिए अलग और आंतरिक होंगे फ़ाइल।) यदि आप हेडर में इस तरह की परिभाषा डालते हैं तो प्रत्येक फ़ाइल जिसमें हेडर शामिल है, का अपना testNum है।

तो static एक शीर्षक में अपने चर पर साथ आप एक अलग चर कि test.h शामिल हर फ़ाइल में testNum कहा जाता है। इसका अर्थ यह है कि यदि आप एक फ़ाइल में testNum सेट करते हैं और एक अलग फ़ाइल में फ़ंक्शन को कॉल करते हैं जो testNum का उपयोग करता है तो यह अलग-अलग वैरिएबल को संदर्भित करता है, जो कि समान नाम होता है।

इस वजह से, हेडर में गैर-कॉन्स static चर घोषित करना लगभग हमेशा गलत होता है।

static के बिना प्रत्येक फ़ाइल में test.h की एक परिभाषा होगी, जिसकी अनुमति नहीं है: प्रत्येक इकाई को केवल एक बार और आपके प्रोग्राम में परिभाषित किया जाना चाहिए। कि हल करने के लिए जिस तरह से घोषित करने के लिए शीर्षक में चर रहा है, लेकिन यह नहीं परिभाषित संकलक बता चर extern है द्वारा जो आप ऐसा करेंगे,:

extern int testNum; // N.B. no "= 1" here 

कि संकलक बताता है एक चर है testNum नामक "बाहरी संबंध" के साथ, इसलिए जब कोड testNum को संदर्भित करता है तो इसका हमेशा एक ही वैरिएबल (आंतरिक लिनज के साथ कुछ नाम नहीं है जो प्रत्येक फ़ाइल में एक अलग इकाई है।) extern परिवर्तनीय घोषित करने के बाद यह सुनिश्चित करना आपकी ज़िम्मेदारी है कार्यक्रम में कहीं भी प्रदान की गई एक परिभाषा है, इसलिए में बिल्कुल एक फ़ाइल (यानी। एक शीर्षलेख में नहीं जो एकाधिक फ़ाइलों में शामिल हो जाता है) आप इसे परिभाषित करते हैं:

int testNum = 1; 
+0

धन्यवाद, यह मेरी समस्या बताता है। जैसा कि मैंने सोचा था कि मैं अपने जावा विकास से स्थिर कैसे काम करता हूं, इस बारे में गलत धारणा बना रहा था, हालांकि मैंने पहले स्थिर देखा और सोचा कि सी ++ स्थैतिक वही है ... उन परिस्थितियों में से एक जहां आप मेरी उम्मीद का जवाब देखते हैं। मैं वास्तव में अपने असली प्रोग्राम को स्थिर मूल्य को कुछ सुरक्षित करने के लिए डिफ़ॉल्ट रूप से पसंद करूंगा, भले ही कोई अजीब कार्यक्षमता न हो, यह सुनिश्चित करने के लिए कि कोई भी जाता है और मेरा मुख्य एचएच बदलता है)। ऐसा लगता है जैसे बाहरी मुझे उस gaurentee से रोकता है कि यह एक वैध डिफ़ॉल्ट मान से शुरू होता है। यह सुनिश्चित करने के लिए कोई रास्ता है? – dsollen

+0

'स्थिर 'का मतलब सी ++ में कई चीजें हैं। _class members_ के लिए यह जावा के समान है, लेकिन आपके पास आपके प्रोग्राम में क्लास सदस्य नहीं है, आपके पास गैर-सदस्य ग्लोबल्स हैं, जो जावा में मौजूद नहीं हैं। –

+0

मुझे नहीं पता कि बाहरी "डिफ़ॉल्ट" मान को रोकने वाले बाहरी या "कुछ सुरक्षित करने के लिए डिफ़ॉल्ट" के बारे में आपका क्या मतलब है। '= 1' मान के साथ क्या गलत है मैंने इसे अपने उत्तर में दिया? –

3

static नाम स्थान दायरे में एक मिथ्या नाम है, और उपयोग नहीं किया जाना चाहिए। यह का अर्थ है कि इकाई घोषित स्थिर है आंतरिक नाम बाध्यकारी है; दूसरे शब्दों में, कि अन्य अनुवाद इकाइयों में एक ही नाम को एक अलग इकाई में संदर्भित करेगा, और परिवर्तनीय परिभाषाओं के मामले में, प्रत्येक अनुवाद इकाई में चर का एक अलग उदाहरण होगा। इसका जीवनकाल पर कोई असर नहीं पड़ता है। (सभी चर घोषित या नाम स्थान दायरे में परिभाषित स्थिर रहते हैं।)

static नाम स्थान दायरे में भी मान्य नहीं है। इसका इस्तेमाल न करें।

शीर्षलेख में एक चर घोषित करने के संबंध में: इसे extern, और static के साथ उपसर्ग करें। यदि एक चर को extern घोषित किया गया है, और कोई प्रारंभिकता नहीं है, तो घोषणा एक परिभाषा नहीं है। पाठ्यक्रम में, इस मामले में, आपको कहीं परिभाषा प्रदान करनी होगी ( एकल स्रोत फ़ाइल में)।

extern int testNum = 5; 
int testNum = 5; 
int testNum;   // implicitly initialized with 0. 

संपादित करें:

कुछ हद तक स्पष्ट करने के लिए: कुछ भ्रम जीवन और नाम बंधन के बीच यहां है: की तर्ज पर कुछ

  • एक वस्तु एक जीवन भर है (ऑटो, स्थिर या गतिशील — या अस्थायी, या अपवाद), और
  • एक नाम किसी इकाई के लिए बाध्य है; यदि नाम एक चर होने के लिए घोषित किया गया है, तो इकाई एक वस्तु है।

नहीं स्थिर जीवन के साथ कीवर्ड static भ्रमित मत करो। (कार्य static हो सकता है, लेकिन कार्यों C++ कोई परिभाषित जीवन है, वे सिर्फ वहाँ रहे हैं।)

इन नियमों के बारे में बहुत orthognal नहीं हैं।मूल रूप से, के साथ जीवन भर के लिए संबंध है:

  • सभी चर नाम स्थान गुंजाइश पर घोषित कर दिया है स्थिर जीवन, हमेशा की तरह,
  • चर स्थानीय गुंजाइश पर घोषित कर दिया ऑटो जीवन जब तक वे static घोषित किया गया है, और
  • चर है कक्षा के दायरे में घोषित कक्षा वर्ग का जीवनकाल होता है जिसमें उन्हें शामिल किया जाता है, जब तक उन्हें static घोषित नहीं किया जाता है। जीवन भर के संबंध में। स्थिर जीवन भर साथ

वस्तुओं main से पहले कुछ समय अस्तित्व में आया, और जब तक आप main से लौटने रहते हैं।

साथ बाध्यकारी नाम के संबंध

:

  • चर नाम स्थान गुंजाइश पर घोषित कर दिया बाहरी नाम बाध्यकारी, जब तक कि वे static घोषित किया गया है, जो मामले में वे आंतरिक नाम बाध्यकारी है (लेकिन static के इस प्रयोग को पदावनत किया गया है), या वे const, कर रहे हैं और extern घोषित नहीं कर रहे हैं,
  • चर वर्ग गुंजाइश पर घोषित कर दिया, बाहरी नाम बाध्यकारी है, भले ही वे static घोषित किया गया है, और
  • अगर
  • ब्लॉक स्कोप पर घोषित चर कोई बाध्यकारी नहीं है।

अंत में, यह घोषणा है कि घोषणा एक परिभाषा है या नहीं। यदि यह एक परिभाषा है, तो स्मृति आवंटित की जाती है और ऑब्जेक्ट (या हो सकता है) प्रारंभ किया गया है। यदि यह परिभाषा नहीं है, तो यह केवल कंपाइलर को बताता है कि घोषणा में घोषित इकाई (ऑब्जेक्ट) के लिए कहीं और परिभाषा है। आम तौर पर, एक चर घोषणा एक परिभाषा है जब तक इसे extern घोषित किया गया है और में प्रारंभकर्ता नहीं है।

+0

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

+0

@dsollen मैंने कुछ स्पष्टीकरण जोड़ने के लिए संपादित किया है। –

1

आप सुनिश्चित करें कि आपके कोड वास्तव में समस्या है इससे पहले कि आप पोस्ट यह पूछ क्या गलत है बनाने के लिए चाहते हो सकता है;)

मैं कॉपी/पेस्ट किया और अपने लेखन त्रुटि को ठीक किया और मैन्युअल को शामिल किया:

#include <iostream> 
using namespace std; 

namespace test{ 
    static int testNum=5; 
    void setNum(int value); 
} 

void test::setNum(int value){ 
    testNum=value; 
} 

int main(){ 
    test::setNum(9); 
    cout<<test::testNum; 
} 

परिणाम:

$ ./a.out 
9 

जो आपने नहीं कहा है वह आपके कार्यक्रम में और क्या है। यदि आपके पास केवल main.cpp से अधिक है, और अपना test.h शामिल करें, तो प्रत्येक .cpp फ़ाइल में testNum की अपनी प्रति होगी। यदि आप उन्हें साझा करना चाहते हैं तो आपको इसे extern के रूप में चिह्नित करने के लिए सभी की आवश्यकता है।

संबंधित मुद्दे