2012-10-26 27 views
10

तो मैं कक्षाओं के बारे में सीख रहा था और मैंने जो कुछ पाया वह मुझ पर काफी अजीब था।क्या कक्षा कार्य/चर का उपयोग करने से पहले घोषित किया जाना चाहिए?

class Nebla 
{ 
    public: 
     int test() 
     { 
      printout(); 
      return x; 
     } 

     void printout() 
     { 
      printout2(); 
     } 

    private: 
     int x,y; 
     void printout2() 
     { 
      cout<<"Testing my class"; 
     } 
}; 

मैंने पाया कि एक कक्षा में मैं कार्यों का उपयोग कर सकते हैं इससे पहले कि मैं उन्हें घोषित (उनमें प्रोटोटाइप)

आप देख सकते हैं मैं decleration से पहले printout(), printout2() इस्तेमाल किया।

और मैं उन्हें

घोषित करने से पहले भी चर का उपयोग कर सकते हैं आप देख सकते हैं मैं return x किया; एक्स घोषित करने से पहले।

मैं घोषणा से पहले कक्षाओं में कार्यों और चर का उपयोग क्यों कर सकता हूं लेकिन कक्षा के बाहर यदि मैं ऐसा करता हूं, तो मुझे कोई त्रुटि मिलती है?

धन्यवाद

+0

मैंने इस के लिए एक विशिष्ट जवाब नहीं देखा है, लेकिन मैंने अनुमान लगाया है कि यह कक्षा में दो पास करने वाले कंपाइलर के कारण है। – chris

+0

@chris आप क्या मतलब है कि कंपाइलर –

+0

पर दो पास कर रहा है [यह टिप्पणी] (http://stackoverflow.com/questions/2632601/why-are-forward-declarations-necessary#comment2646159_2632601) मजबूती से प्रबल होता है वह अनुमान है। सवाल थोड़ा सा अवधारणा से संबंधित है। – chris

उत्तर

13

अच्छा सवाल; मैंने इस सुविधा पर वर्षों के बारे में सोचने के बिना भरोसा किया है। मैंने स्ट्रास्ट्रप के सी ++ प्रोग्रामिंग भाषा और एनोटेटेड सी ++ संदर्भ मैनुअल सहित उत्तर खोजने के लिए कई सी ++ किताबों को देखा, लेकिन कोई भी अंतर स्वीकार या व्याख्या नहीं करता है। लेकिन, मुझे लगता है कि मैं इसके माध्यम से तर्क कर सकता हूं।

कारण, मेरा मानना ​​है कि आपका उदाहरण काम करता है कि आपके test और printout के निकाय वास्तव में आपकी फ़ाइल में दिखाई नहीं दे रहे हैं।

class MyClass { 
    void someFun(); 
    int x; 
}; 

void MyClass::someFun() { 
    x = 5; 
} 

एक बार जब हम ऐसा फिर से लिखने, यह स्पष्ट हो जाता: कोड

class MyClass { 
    void someFun() { 
    x = 5; 
    } 
    int x; 
}; 

... जो चर घोषित करने के लिए इससे पहले कि आप उन्हें इस्तेमाल होने के नियम का उल्लंघन कर रहा है, वास्तव में के बराबर है कि आपके MyClass परिभाषा के अंदर की सामग्री वास्तव में घोषणाओं की सूची है। और वे किसी भी क्रम में हो सकते हैं। आप घोषित किए जाने तक x पर भरोसा नहीं कर रहे हैं। मुझे यह सच होने के बारे में पता है क्योंकि यदि आप उदाहरण को फिर से लिखना चाहते हैं, तो

void MyClass::someFun() { 
    x = 5; 
} 

class MyClass { 
    void someFun(); 
    int x; 
}; 

... यह अब संकलित नहीं होगा! इसलिए कक्षा परिभाषा पहले (सदस्यों की पूरी सूची के साथ) आती है, और फिर आपकी विधियां कक्षा में घोषित आदेश के संबंध में किसी भी सदस्य का उपयोग कर सकती हैं।

पहेली का अंतिम भाग यह है कि सी ++ कक्षा परिभाषा के बाहर किसी वर्ग के सदस्य को घोषित करने पर रोक लगाता है, इसलिए जब संकलक आपकी कक्षा परिभाषा को संसाधित करता है, तो यह वर्ग के सदस्यों की पूरी सूची जानता है। यह स्ट्रॉस्ट्रप के के पी .170 पर बताया गया है एनोटेटेड सी ++ संदर्भ मैनुअल: "सदस्य सूची कक्षा के सदस्यों के पूर्ण सेट को परिभाषित करता है। कोई भी सदस्य कहीं और नहीं जोड़ा जा सकता है।"

मुझे इसकी जांच करने के लिए धन्यवाद; मैंने आज कुछ नया सीखा। :)

+0

कमाल का जवाब, आप इस जवाब के 100% निश्चित हैं? –

+0

प्रशंसा के लिए धन्यवाद। मुझे यकीन है कि मैंने जो लिखा है, वह मानक और कंपाइलर संगतता के बारे में चिंतित होने पर पर्याप्त नहीं हो सकता है। मुझे लगता है कि एस्केप्लर का जवाब मेरी तुलना में "100% निश्चित" है। – Philip

+0

हाँ दोनों महान उत्तर हैं, लेकिन मुझे आपकी पसंद है: डी, ​​आपने इसे समझाया। –

0

कारण आप ऐसा करने में सक्षम हैं, क्योंकि समय आप test, printout या printout2 फोन द्वारा, वे पहले से ही बनाया गया है जाएगा। यदि आप कार्यान्वयन से पहले मनमाने ढंग से कार्य के बाहर फ़ंक्शन को कॉल करते हैं, तो आपको एक त्रुटि मिल जाएगी।

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

+0

क्या आप अधिक स्पष्ट/स्पष्ट स्पष्टीकरण प्रदान कर सकते हैं? –

+0

मुझे देखने दो मैं इसे सही ढंग से समझता हूं, ऐसा इसलिए है क्योंकि ऑब्जेक्ट्स घोषित होने के बाद सभी फ़ंक्शन/चर घोषित किए जाते हैं? –

4

बस इसे स्पष्ट करने के लिए, यह सी ++ मानक द्वारा आवश्यक है, न केवल कई संकलक वर्ग परिभाषाओं को संभालने के तरीके के लिए।

N3242 3.3.7:

एक नाम एक वर्ग में घोषित की क्षमता गुंजाइश न केवल घोषणा के नाम के बिंदु निम्नलिखित कथात्मक क्षेत्र के होते हैं, लेकिन यह भी सभी कार्य निकायों की, ब्रेस-या गैर-स्थैतिक डेटा सदस्यों के -equal-startizers, और उस वर्ग में डिफ़ॉल्ट तर्क (नेस्टेड कक्षाओं में ऐसी चीजों सहित)।

1

फिलिप की अच्छी प्रतिक्रिया इसके अलावा, Stroustrup डिजाइन और सी ++ के विकास में नाम लुक नियम का एक अच्छा विवरण देता है। यह "6.3 स्पष्टीकरण" में वर्णित है। 6.3.1.1 में, "एआरएम नाम लुक नियम", वह 2 नियम एआरएम में परिभाषित का उल्लेख है:

[1] प्रकार परिभाषा नियम: एक प्रकार का नाम इसके बाद एक कक्षा में नए सिरे से परिभाषित नहीं किया जा सकता वहाँ इस्तेमाल किया गया है।

[2] पुनर्लेखन नियम: इनलाइन परिभाषित सदस्य कार्य का विश्लेषण किया जाता है जैसे कि उन्हें अपनी कक्षा घोषणाओं के अंत के तुरंत बाद परिभाषित किया गया था।

तो आपके मामले में यह पुनः लिखने के नियम (फिलिप के रूप में) के रूप में लागू होगा, यही कारण है कि आप उन वर्ग के सदस्यों को संदर्भित कर सकते हैं।

यह पुस्तक मुख्य रूप से ऐतिहासिक रुचि (यह '94 में लिखा गया है) हो सकती है, लेकिन मुझे लगता है कि उन नियमों को आज भी उसी तरह लागू किया जाता है।