2010-11-04 11 views
7

मुझे पता है कि आप आमतौर पर एक .cpp फ़ाइल के भीतर से एक स्थिर सदस्य चर प्रारंभ करते हैं। लेकिन मेरा सवाल है: आप पर क्यों हैं? सी ++ स्थैतिक सदस्य चर प्रारंभ करने के लिए आप _have_ क्यों करते हैं?

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

main() { 
    int sz = A::x.size(); 
} 

यह एक संकलक त्रुटि देता है: undefined reference to 'A::x'

हालांकि, इस:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

// Initialize static member 
vector<int> A::x; 

main() { 
    int sz = A::x.size(); 
} 

compiles और ठीक चलाता

यहाँ एक उदाहरण है।

मैं समझ सकता हूं कि क्या मैं डिफ़ॉल्ट कन्स्ट्रक्टर के अलावा किसी अन्य का उपयोग कर वेक्टर शुरू कर रहा था, लेकिन मैं नहीं हूं। मैं सिर्फ आकार 0 के एक वेक्टर चाहता हूँ। निश्चित रूप से, किसी भी स्थिर सदस्यों को प्रोग्राम प्रारंभिकरण पर स्मृति आवंटित करनी होगी, तो संकलक केवल डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग क्यों नहीं करता है?

उत्तर

14

यह प्रारंभिकता के बारे में नहीं है, यह लगभग परिभाषा है। या अधिक सटीक: यह जानने के जो संकलन इकाई (सीपीपी) के बारे में है वस्तु (जो अद्वितीय रूप से कहीं से परिभाषित करने की है) का आयोजन करेगा

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

+2

+1 लेकिन आपको डुप्लिकेट में से एक को हटाना चाहिए। वस्तुओं के लिए, आरएआईआई परिभाषा का परिणाम प्रारंभिक बनाता है (भले ही केवल डिफ़ॉल्ट कन्स्ट्रक्टर द्वारा)। क्या यह कच्चे पॉइंटर्स, बिल्टिन प्रकारों जैसे 'int' के लिए काम करता है? –

+0

मेरा मतलब था कि यदि आप चाहते हैं तो आप वहां प्रारंभिक जोड़ सकते हैं। मैं परिशुद्धता जोड़ दूंगा। – Klaim

+0

@ स्टेव पीओडी प्रकार कन्स्ट्रक्टर केवल वाक्य रचनात्मक हैं, इसलिए हाँ यह काम करता है, लेकिन यह वास्तव में कुछ भी नहीं करता है (या इससे भी अधिक सटीक होने के लिए, इसे कुछ भी करने की अनुमति नहीं है - सी ++ मानक द्वारा)। –

2

जो आप प्रारंभिक कॉल कहते हैं वह परिभाषा है। आपको स्थिर सदस्य को कहीं भी परिभाषित करने की आवश्यकता है। कक्षा के अंदर हिस्सा सिर्फ एक घोषणा है।

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

8

आप इसे एक संकलन इकाई के बिंदु से देख रहे हैं।

लेकिन भाषा को कई संकलन इकाइयों द्वारा संभवतः संभावित रूप से माना जा सकता है। तो अब किस संकलन इकाई में स्थिर वस्तु बनाई गई है? असल में संकलक को यह निर्णय लेने की अनुमति नहीं है और इंजीनियर को निर्णय लेना चाहिए।

3

undefined reference to 'A::x' एक कंपाइलर त्रुटि नहीं है; यह एक लिंकर त्रुटि है। इसका मतलब है कि A::x की परिभाषा किसी भी अनुवाद इकाइयों में नहीं मिल सकती है जो आपके प्रोग्राम को बनाने के लिए एक साथ जुड़े हुए हैं। स्टेटिक सदस्य चर के बाहरी संबंध हैं और उन्हें एक अनुवाद इकाई में परिभाषित किया जाना चाहिए। बाहरी लिंकेज के साथ कुछ भी संकलक द्वारा उत्पन्न परिभाषा नहीं होगी जबतक कि आप एक नहीं लिखते।

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