2012-08-06 25 views
6
void foo() 
{ 
    bar();   // error: ‘bar’ has not been declared 
} 

void bar() 
{ 
} 

namespace N 
{ 
    void foo() 
    { 
     N::bar(); // error: ‘bar’ is not a member of ‘N’ 
    } 

    void bar() 
    { 
    } 
} 

class C 
{ 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    { 
    } 
}; 

उनकी घोषणा के ऊपर कार्यों को कॉल करने के इस असंगतता के पीछे तर्क क्या है? मैं इसे कक्षा के अंदर कैसे कर सकता हूं, लेकिन नामस्थान के अंदर या वैश्विक दायरे में नहीं?उनकी घोषणा के ऊपर कॉलिंग फ़ंक्शंस

+0

शायद, संकलक, जबकि 'सी' संकलक केवल एक बार गुजरता है, वर्ग घोषणा भीतर वर्ग विधि कार्यान्वयन के माध्यम से कई बार गुजरता है। कुछ विरासत हो सकती है, क्योंकि foo() अनिवार्य रूप से सी-फ़ंक्शन –

+0

है और स्थिर शून्य foo से स्थिर को हटाने के बाद परिणाम क्या है ?? – perilbrain

+0

@ अज्ञात, यह कुछ भी नहीं बदलता है – SingerOfTheFall

उत्तर

3

आप कक्षा के अंदर या कक्षा घोषणा के बाद, या प्रत्येक में सदस्य कार्यों को परिभाषित कर सकते हैं।

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

आपका कोड

class C { 
    static void foo() 
    { 
     C::bar(); // works just fine 
    } 

    static void bar() 
    {  } 
}; 

class C { 
    static void foo(); 
    static void bar(); 
}; 

void C::foo() 
{ C::bar(); } 

void C::bar() 
{  } 

के रूप में ही संकलित करता है तथा अब वहाँ दृश्यता में कोई जादू नहीं है, क्योंकि कार्यों सब देख सकते हैं सब कुछ वर्ग में घोषित कर दिया।

0

खैर शायद क्योंकि आप एक ही स्थान पर अपनी कक्षा घोषणा है, और संकलक आसानी से इसे के सदस्यों के बारे में जानकारी प्राप्त कर सकते हैं।

दूसरी ओर, एक नामस्थान में कई अलग-अलग फाइलों में सामान हो सकता है, और आप संकलक को उनसे देखने की उम्मीद नहीं कर सकते हैं, क्योंकि यह नहीं पता कि पहले स्थान पर कहां देखना है।

इससे बचने के लिए, बस function prototypes का उपयोग करें।

0

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

लेकिन एक नामस्थान अलग है, कार्य संबंधित नहीं हैं। इसका मतलब है कि एक समारोह नामस्थान के अंदर हर दूसरे कार्यों के साथ काम करने का इरादा नहीं है।

तो विभाजित घोषणा और परिभाषाएं सबसे अच्छी चीज हैं जो आप कर सकते हैं।

foo() हैं जरूरतों bar() इसकी सबसे अधिक संभावना एक ही घोषणा फ़ाइल में होने जा रहा है, और इस तरह से काम करेगा

1
  1. नेमस्पेस फिर से खोल दी जा सकती है और नई चीजों किसी भी स्थान में जोड़ा जा सकता है। कक्षाओं को फिर से खोल नहीं किया जा सकता है - उनकी सभी सामग्री एकल स्थान पर रखी जानी चाहिए।

  2. समारोह प्रोटोटाइप नामस्थान में लेकिन कक्षाओं में नहीं कानूनी है।

आप

namespace n 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

लिख सकते हैं लेकिन नहीं

class C 
{ 
    void foo(); 

    void bar() 
    { 
     foo(); 
    } 

    void foo() 
    { 
    } 
} 

तो कक्षाएं ऐसी सुविधा भी बहुत कुछ की जरूरत है और यह नामस्थान के लिए की तुलना में उनके लिए इसे लागू करने के बहुत आसान है।

0

स्टैंडर्ड

3.3.7 कक्षा दायरे से नीचे बोली देखें [basic.scope.class]

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

2) कक्षा एस में उपयोग किया जाने वाला नाम एन संदर्भ में उसी घोषणा को संदर्भित करेगा और में फिर से मूल्यांकन किया जाएगा। इस नियम के उल्लंघन के लिए एस नो डायग्नोस्टिक का पूरा दायरा आवश्यक है।

typedef int c; 
enum { i = 1 }; 

class X { 
    char v[i]; // error: i refers to ::i 
       // but when reevaluated is X::i 
    int f() { return sizeof(c); } // OK: X::c 
    char c; 
    enum { i = 2 }; 
};