2015-09-20 9 views
14

पर विचार करें नीचे दिए गए कोड:क्यों एक इनलाइन घोषणा एक अपूर्ण प्रकार नहीं है?

struct Foo { 
    struct Bar; 
    Foo() 
    { 
     Bar bar; // Why isn't Bar an incomplete type?! 
    } 
    struct Bar {}; // Full definition 
}; 

// struct Bar {}; // fails to compile due to incomplete type 

int main() 
{ 
    Foo foo; 
} 

यह कम से कम 2 compilers (gcc5.2, clang3.5) के तहत ठीक संकलित करता है। मेरा प्रश्न है: के रूप में मैं निर्माता से ऊपर इसे आगे-घोषित

  • क्यों नहीं Bar निर्माता Foo::Foo में एक अधूरी प्रकार माना जाता है, लेकिन पूरी तरह से निर्माता के अंदर इसका इस्तेमाल?

जब भी मैं कक्षा के बाहर Foo::Bar ले जाते हैं, दूसरे शब्दों Bar में, एक स्टैंड-अलोन वर्ग बन जाता है मैं उम्मीद

error: aggregate 'Foo::Bar bar' has incomplete type and cannot be defined

+2

सदस्य फ़ंक्शन निकाय इस तरह व्यवहार करते हैं जैसे कि उन्हें परिभाषित किया गया है (यानी, कक्षा परिभाषा के बाद)। –

+0

मुख्य कारण यह है कि संकलक कक्षा के अंदर सभी परिभाषाओं की स्थानीय खोज कर सकता है, जब यह निर्धारित करता है कि प्रत्येक प्रकार को कैसे संभालना है। दायरे की पूरी तरह से जांच की जाती है, क्योंकि यह आपके कार्यक्रम का एक छोटा सा हिस्सा है, और इसे स्रोत कोड में घोषणाओं के क्रम पर भरोसा करने की आवश्यकता नहीं है। – tp1

उत्तर

8
सदस्य विनिर्देश के भीतर

वर्ग समारोह शरीर के भीतर पूरा माना जाता है मिलता है, से मसौदा सी ++ मानक खंड 9.2[class.mem]:

A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification

आप इसका मतलब है यहां तक ​​कि घोषित Bar (see it live) को अग्रेषित करने की जरूरत नहीं है:

struct Foo { 
    Foo() 
    { 
     Bar bar; 
    } 
    struct Bar {}; 
}; 

आगे की घोषणा अनुभाग 3.3.7 paragraph 2 and 3 के उल्लंघन से बचने में उपयोगी हो सकता है।

+0

धन्यवाद! आपके नवीनतम संपादन के बारे में, ऐसा लगता है कि जब भी आंतरिक कक्षा में एक अलग पहुंच निर्दिष्ट होता है तो मुझे घोषित करना होगा। उदाहरण देखें [यह] (http://stackoverflow.com/a/32685194/3093378), अगर मैं आगे की घोषणा को हटा देता हूं तो कोड संकलित नहीं होगा (जीसीसी और क्लैंग दोनों के साथ प्रयास किया जाएगा)। – vsoftco

+0

@ vsoftco दाएं, उस विशिष्ट मामले में यह आगे की घोषणा के बिना काम करता है क्योंकि यह उन स्थानों में से एक नहीं है जहां कक्षा को ऊपर दिए गए अनुच्छेद I द्वारा परिभाषित अनुसार पूर्ण माना जाता है। –

+0

धन्यवाद, क्रिस्टल स्पष्ट! – vsoftco

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