2014-08-27 9 views
5

स्टेटिक प्रारंभ में अच्छी तरह से, इस विषय में वर्णित है here और यहां तक ​​कि इस साइट hereस्टेटिक प्रारंभ

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

लेकिन मैं इस कोड है:

template <typename T> 
class A{ 
public: 
    int _data; 
    T _obj; 
    A(int data) :_data(data){} 
}; 

template <typename T> 
class B{ 
public: 
    const static B<T> nullObj; 
    B(int data) :_a(new A<T>(data)){} 
    A<T> *_a; 
}; 

template <typename T> 
class C{ 
public: 
    const static C<T> nullObj; 
    C() :_a(nullObj._a){} 
    C(bool t) :_a(B<T>::nullObj._a){ 
     _a->_data++; //FAILS HERE! 
    } 
    A<T> *_a; 
}; 

template <typename T> 
const B<T> B<T>::nullObj(0); 

template <typename T> 
const C<T> C<T>::nullObj(false); 

class _B{}; 
class _A{ public: _A(){}; C<_B> g; }; 

int main(){ 
    return 0; 
} 

और यह मुख्य() फंक्शन प्रवेश करने से पहले कार्यावधि में विफल रहता है, क्योंकि यह पहलेconst B<T> B<T>::nullObj(0); आरंभ नहीं हो जाता const C<T> C<T>::nullObj(false);प्रारंभ करने की कोशिश करता है। एक फ़ाइल में अपनी स्थिति के बावजूद।

यह पहले स्थैतिक चर से पहले दूसरे स्थैतिक चर को प्रारंभ करने का प्रयास क्यों करता है? क्या सी ++ स्टैंडअर्ट में अध्याय मौजूद है जहां स्थिर प्रारंभिक क्रम के अनुक्रम के साथ वास्तविक स्थिति का वर्णन किया गया है?

+0

"क्यों यह पहली स्थिर चर से पहले दूसरी स्थिर चर को प्रारंभ करने की कोशिश करता है?" यहां कोई "पहला" और कोई "दूसरा" चर नहीं है, यह टेम्पलेट्स की एक जोड़ी है जिससे आप शून्य, दो, चार, छः, आठ आदि का उत्पादन कर सकते हैं। टेम्पलेट इंस्टेंटेशन पर स्थिर चर। – dasblinkenlight

+0

@dasblinkenlight, ठीक है, आप सही हैं, तो सवाल यह है: "यह पहले स्थिर से पहले दूसरे स्थिर टेम्पलेट को प्रारंभ करने का प्रयास क्यों करता है?" – Arkady

उत्तर

5

सी ++ स्टैंडर्ड, खंड 14.7.1 [temp.inst]:

जब तक कि एक वर्ग टेम्पलेट या एक सदस्य टेम्पलेट के एक सदस्य को स्पष्ट रूप से instantiated कर दिया गया है या स्पष्ट रूप से विशेष, सदस्य की विशेषज्ञता परोक्ष instantiated है जब विशेषज्ञता को संदर्भ में संदर्भित किया जाता है जिसके लिए सदस्य परिभाषा मौजूद होती है; विशेष रूप से , एक स्थिर डेटा सदस्य का प्रारंभ (और कोई भी संबद्ध दुष्प्रभाव) नहीं होती है जब तक स्थिर डेटा सदस्य ही एक तरीका है कि स्थिर डेटा सदस्य की परिभाषा की आवश्यकता में प्रयोग किया जाता है अस्तित्व के लिए


C<T>B<T> से पहले instanciated है, इसलिए प्रारंभ के आदेश में अच्छी तरह से परिभाषित किया गया है, और है:

1)const static C<T> nullObj;

2)const static B<T> nullObj;

के बाद से C निर्माता भिन्नता B<T>::nullObj._a, आप व्यवहार अपरिभाषित है।

समाधान:

आप किसी भी तरह स्थिर सदस्य B<_B>::nullObj का उपयोग करना चाहिए यह प्रारंभ करने के लिए, उदाहरण के लिएयदि आप कार्य करें:

class _B{}; 
class _A{ public: _A() : b(B<_B>::nullObj) {}; B<_B> b; C<_B> g; }; 

फिर B<_B>::nullObj वास्तव में प्रारंभ से पहले C निर्माता यह

+0

मैंने सी <_B> से पहले बी <_B> शुरू करने के लिए _A को संशोधित किया: 'कक्षा _ ए {सार्वजनिक: _ ए(): बी (0) {}; बी <_B> बी; सी <_B> जी; }; 'अभी भी यह विफल रहता है। – Arkady

+0

@ अर्कडी मेरे संपादन को देखते हैं, आप अभी भी स्थिर सदस्य – quantdev

+0

को तत्काल नहीं कर रहे हैं हां, जो हल करता है और सबकुछ बताता है, धन्यवाद! लेकिन अभी भी एक सवाल है: क्यों कन्स्ट्रक्टर प्रारंभिक सूची में जी (0) जोड़ना समस्या हल करता है? अर्थात। 'बी (0), जी (0)' - भी काम करता है। – Arkady

2

टेम्पलेट उदाहरण तब तक परिभाषित नहीं किए जाते जब तक उन्हें तत्काल नहीं किया जाता है। पहली बार C<> तत्काल है _A के निर्माता में है। और B<>C<> द्वारा तत्काल किया गया है, इसलिए B<_B> परिभाषित किया गया है जब C<_B> तत्काल है। इसलिए C<_B>B<_B> से पहले है।

_A की परिभाषा से पहले आप स्पष्ट टेम्पलेट तत्काल template class B<_B>; जोड़ सकते हैं, जो मुझे विश्वास है कि आदेश को ठीक करना चाहिए।

+0

मैंने इसे चेक किया।यदि मैं _A को 'class _A {public: _A() में बदलता हूं: b (0) {}; बी <_B> बी; सी <_B> जी; }; ', इसलिए बी <_B> अब सी <_B> से पहले शुरू किया जाना है, अभी भी असफल रहा है। – Arkady

+0

दिलचस्प बात यह है कि अगर मैं प्रारंभिक सूची में 'g (0)' जोड़ता हूं तो यह ठीक लगता है। या तो अपरिभाषित व्यवहार है या एक नियम है जो मुझे अज्ञात है। इन सभी संस्करणों (आपका मूल और आपका नया '_ ए') स्पष्ट तत्कालता के साथ मेरे लिए काम करता है (ध्यान दें कि मेरे पास मूल रूप से टाइपो था, यह 'बी <_B>' होना चाहिए)। – user2079303

+0

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

1

बिंदु _a के निर्माता में है की जरूरत है। cppreference राज्यों के रूप में:

वर्ग टी के लिए डिफ़ॉल्ट निर्माता तुच्छ है (यानी कोई कार्रवाई नहीं करता है) करता है, तो निम्न में से सभी सत्य है:

  • निर्माता है नहीं उपयोगकर्ता द्वारा प्रदान की (जो implicitly- है परिभाषित या डिफॉल्ट)
  • टी है कोई आभासी सदस्य कार्यों
  • टी है कोई आभासी आधार वर्ग
  • टी ब्रेस या बराबर initializers के साथ कोई गैर स्थिर सदस्य हैं। (के बाद से सी ++ 11)
  • टी का हर प्रत्यक्ष आधार एक छोटी सी डिफ़ॉल्ट निर्माता है
  • वर्ग प्रकार का हर गैर स्थिर सदस्य एक छोटी सी डिफ़ॉल्ट निर्माता

यह is not trivially constructible

class _A{ public: _A(){} }; 
है

जबकि यह

class _A{ public: }; 

और उदाहरण के मामले में

class _A{ public: _A(){} C<_B> g; }; 

मतलब यह है कि निर्माता वर्ग के सदस्यों के लिए प्रारंभ दिनचर्या प्रदर्शन करता है: यह निश्चित रूप से एक छोटी सी निर्माता नहीं है। मानक के अनुसार 14.7.1 [temp.inst]

स्थिर डेटा सदस्य का प्रारंभिक (और कोई भी संबद्ध दुष्प्रभाव) तब तक नहीं होता है जब तक स्थिर डेटा सदस्य स्वयं इस तरह से उपयोग नहीं करता है स्थिर डेटा सदस्य की परिभाषा

मौजूद हैं और के बाद से गैर तुच्छ निर्माता सिर्फ हमारे लिए स्थैतिक चर प्रारंभ करने के लिए उपयोग (की जरूरत नहीं) प्रदान की, सीआरटी अपना काम शुरू होता है और आरंभ शुरू होता है

const static C<T> nullObj; 

जो बदले में कुछ unitialized dereferences और आप व्यवहार अपरिभाषित है।

quantdev के रूप में हल करने के लिए, के रूप में कहा गया है, या तो आप इस प्रक्रिया से पहले B<_B>::nullObj प्रारंभ करने या अपने कोड के डिजाइन बदल जाते हैं।

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