2012-07-04 6 views
7

क्या मैं 5.2.8.3: ... If the type of the expression is a class type, the class shall be completely-defined. में मानक को सही ढंग से पढ़ रहा हूं यदि प्रकार "पूरी तरह से परिभाषित नहीं" है तो इसका मतलब है कि निम्न प्रोग्राम अपरिभाषित है?एक आगे घोषित प्रकार अपरिभाषित व्यवहार पर टाइपिड का उपयोग कर रहा है?

foo.cpp:

struct foo 
{ 
    virtual void a(){} 
}; 

struct bar : foo 
{ 
    virtual void a(){} 
}; 

bar abar; 

foo& get_some_foo() 
{ 
    return abar; 
} 

main.cpp:

#include <iostream> 
#include <typeinfo> 

struct foo; 

foo& get_some_foo(); 

int main() 
{ 
    foo& a_ref_foo(get_some_foo()); 

    std::cout << "a_ref_foo typeid name: " << typeid(a_ref_foo).name() << std::endl; 

    return 0; 
} 

MSVC10 आउटपुट: `a_ref_foo typeid नाम: struct foo '

उत्तर

10

जब मैं के साथ अपने कोड संकलन:

g++ foo.cpp main.cpp -o main 

मैं:

main.cpp: In function ‘int main()’: 
main.cpp:12:52: error: invalid use of incomplete type ‘struct foo’ 
main.cpp:4:8: error: forward declaration of ‘struct foo’ 

कि मानक मेरी व्याख्या के साथ सहमत हैं, कि तुम एक अधूरी प्रकार के typeid लागू नहीं कर सकते हैं - और a_ref_foo एक अपूर्ण प्रकार का है, क्योंकि foo की पूर्ण परिभाषा दिखाई नहीं दे रही है। main.cpp (मैंने जो लाइनें जोड़ दी हैं) बीमार है, और एक निदान की आवश्यकता है।

अद्यतन:

मैं दृश्य स्टूडियो 2010 एक्सप्रेस के साथ इस मुद्दे reproduced गए हैं। भाषा एक्सटेंशन अक्षम होने के बावजूद, यह मामूली कार्यक्रम:

#include <typeinfo> 

struct foo; 

int main() 
{ 
    typeid (foo); 
    return 0; 
} 

कोई डायग्नोस्टिक संदेश के साथ संकलित नहीं हुआ। जीसीसी 4.7 के साथ, मैं मिलता है:

main.cpp: In function ‘int main()’: 
main.cpp:7:14: error: invalid use of incomplete type ‘struct foo’ 
main.cpp:3:8: error: forward declaration of ‘struct foo’ 

यही नियम:

अभिव्यक्ति के प्रकार के एक वर्ग के प्रकार होती है, वर्ग होगा पूरी तरह से परिभाषित।

1 99 8, 2003 और आईएसओ सी ++ मानक के 2012 संस्करणों में दिखाई देता है।

विजुअल स्टूडियो में एक बग की तरह दिखता है। (अगर कोई इसे माइक्रोसॉफ्ट को रिपोर्ट करना चाहेगा, तो आगे बढ़ें।)

+4

इस मामले में, "इच्छा" का उपयोग यह बीमार है, क्योंकि यह एक निदान योग्य नियम है (यानी, यह नहीं कहा जाता है कि "कोई निदान आवश्यक नहीं है" और स्पष्ट रूप से अपरिभाषित व्यवहार के रूप में वर्णित नहीं है)। –

+0

@ आर। मार्टिन्होफर्नैंड्स: धन्यवाद, मैंने जवाब अपडेट किया है। (सी मानक, जिसके साथ मैं अधिक परिचित हूं, अलग-अलग "होगा" का उपयोग करता है; एक "इच्छा" का उल्लंघन जो एक स्पष्ट * बाधा में नहीं है * प्रोग्राम के व्यवहार को अपरिभाषित करता है। सी ++ नियम धारा 1.4 में शामिल होते हैं, " कार्यान्वयन अनुपालन "।) –

+0

आपकी धारणा के बारे में आपकी धारणा सही थी। उसके लिए माफ़ करना। मैंने अभी भी जीसीसी पर कोशिश की और वही त्रुटियां मिलीं। डब्ल्यू 4 के साथ इसका दिलचस्प एमएसवीसी 10 चेतावनी भी नहीं देता है। – Zac

0

आपका कार्यक्रम पूरी तरह से सही है, क्योंकि कार्यों get_some_foo और bar ग्लोबल्स हैं। तो bar पूरी तरह से परिभाषित किया गया है, लेकिन यदि आप bar का main.cpp में एक संस्करण परिभाषित करते हैं, तो इसे टाइपिड में पैरामीटर के रूप में उपयोग करें, या संकलन करते समय त्रुटि उत्पन्न होती है।

+0

अनुवाद इकाई में जहां 'मुख्य' परिभाषित किया गया है, प्रकार' foo' ** ** अपूर्ण है। –

5

हां, कार्यक्रम खराब है (अपरिभाषित व्यवहार के कारण)।

आपको आश्चर्य तो क्यों, तो आप पर विचार करना चाहिए कि typeid एक भी ऑपरेटर है, लेकिन यह गैर बहुरूपी प्रकार के लिए की तुलना में बहुरूपी प्रकार के लिए पूरी तरह से अलग अर्थ विज्ञान है।विशेष रूप से, यदि foo पॉलिमॉर्फिक है (कम से कम एक वर्चुअल फ़ंक्शन है, तो typeidवास्तविक प्रकार (इस मामले में bar) के लिए ऑब्जेक्ट का संदर्भ देगा, जबकि इस प्रकार में कोई वर्चुअल फ़ंक्शन नहीं है तो यह होगा (इस मामले foo में) स्थिर अभिव्यक्ति के प्रकार के लिए type_info ऑब्जेक्ट के संदर्भ लौटने।

संकलक के लिए उचित कोड उत्पन्न करने के लिए, संकलक पता होना चाहिए जगह है जहाँ typeid प्रयोग किया जाता है पर जो दो मामलों में लागू होता है। यदि प्रकार अपूर्ण है, तो वह जानकारी मौजूद नहीं है कंपाइलर

+0

आप समझ में आते हैं - जो मैं मान रहा था, संकलक केवल गैर-पॉलीमोर्फिक प्रकार देखता है। मैं इस व्यवहार में भाग गया और यह समझने की कोशिश कर रहे मानक के माध्यम से खुदाई कर रहा था कि इसका क्या अर्थ है। धन्यवाद। – Zac

+0

@Zac: कंपाइलर को आपके कोड को खारिज कर देना चाहिए था। यह अनिर्धारित व्यवहार नहीं है, बल्कि एक बीमार गठित कार्यक्रम है जो संकलक द्वारा त्रिकोणीय रूप से निदान योग्य है। –

+0

वह भेद (गतिशील बनाम स्थैतिक प्रकार) टाइपिड के उपयोग पर लागू नहीं होता है जहां तर्क एक प्रकार का नाम होता है, जो जीसीसी कम से कम एक त्रुटि के रूप में झंडे भी करता है, उदाहरण: struct Foo; कॉन्स std :: type_info और fooType = typeid (Foo); –

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